当前位置: 首页 > news >正文

P7708 题解

题目链接

前言

莫队好题,比较板但又比较考转移的思维。

思路

很简单的发现是对操作序列进行莫队。

先对问题进行转换。

首先对于两种修改,第一种修改显然是没有第二种好写的,考虑将第一种转换为第二种。想到对于每一次第一种修改可以单开一个点,将其值赋值为要修改的值,这样就可以将第一种修改转换为第二种修改了,即将赋值转换为这个点与新开的点交换点值,这样方便撤销修改。

接下来就应该考虑 add()del() 的写法了。

由于删除和扩展到的如果是查询点只有加与减的差别。如果是修改点,由于修改的操作时交换,换两次相当于没换,删除和扩展的操作应是一样的

对于向右扩展与删除,是不会影响到前面的修改的,但对于向左的扩展与删除显然是会的,所以需要分开写。我们假设我们不在 \(a\) 数组上修改,而是在 \(rfl\) 数组上修改,\(rfl_i\) 表示进行一系列的交换后 \(i\) 位置所对应的原来的\(a\) 数组上的位置,再开两个数组分别为 \(pos\)\(cnt\)\(pos_i\) 表示原来 \(a\) 数组上的 \(i\) 位置现在在 \(rfl\) 数组上对应的位置下标,\(cnt_i\) 表示原来的 \(a\) 数组中 \(i\) 的位置在答案中加了几次。

先考虑更简单的向右扩展或删除。

向右扩展显然是在 \(rfl\) 数组 上进行修改。如果扩展到的是查询点,直接修改答案与 \(cnt\) 数组即可。如果扩展到的是修改点,假设交换的位置为 \(u\)\(v\),直接交换 \(rfl\) 数组上对应位置的值,并且修改 \(pos\) 数组上对应位置的值,即交换 \(rfl_u\)\(rfl_v\) 的值,同时交换 \(pos_{rfl_u}\)\(pos_{rfl_v}\) 的值。

再考虑向左扩展或删除。

显然向左扩展我们应该在 \(a\) 数组 上进行操作,因为向左扩展或删除的操作显然是最先进行的。如果是查询点方法与向右类似,不再多说。如果是修改点,首先应该减去 \(u\)\(v\) 两点对答案的贡献,显然直接交换 \(a\) 的值是不行的,不然多次交换后会出问题。所以我们应该交换其在 \(rfl\) 对应位置上的值,并交换 \(cnt\) 数组上的值。毕竟如果最开始就将两个位置的值交换了,那后续对这两个位置的查询次数显然也是要交换的。总结下来就是要交换 \(pos_u\)\(pos_v\) 的值,交换 \(rfl_{pos_u}\)\(rfl_{pos_v}\) 的值,交换 \(cnt_u\)\(cnt_v\) 的值。

然后外面套个莫队板子就做完了。

关键部分代码

其他都是莫队板子没什么好看的。

struct node1 {int op, u, v;
} b[maxn];
usd answer = 0;
void addl(int i) {if(b[i].op == 0) { int x = b[i].u; answer += a[x], cnt[x]++; AC; }answer -= a[b[i].u] * cnt[b[i].u];answer -= a[b[i].v] * cnt[b[i].v];swap(cnt[b[i].v], cnt[b[i].u]);swap(pos[b[i].u], pos[b[i].v]);swap(rfl[pos[b[i].u]], rfl[pos[b[i].v]]);answer += a[b[i].u] * cnt[b[i].u];answer += a[b[i].v] * cnt[b[i].v];
}
void dell(int i) {if(b[i].op == 0) { int x = b[i].u; answer -= a[x], cnt[x]--; AC; }answer -= a[b[i].u] * cnt[b[i].u];answer -= a[b[i].v] * cnt[b[i].v];swap(cnt[b[i].v], cnt[b[i].u]);swap(pos[b[i].u], pos[b[i].v]);swap(rfl[pos[b[i].u]], rfl[pos[b[i].v]]);answer += a[b[i].u] * cnt[b[i].u];answer += a[b[i].v] * cnt[b[i].v];
}
void addr(int i) {if(b[i].op == 0) { int x = rfl[b[i].u]; answer += a[x], cnt[x]++; AC; }swap(rfl[b[i].u], rfl[b[i].v]);swap(pos[rfl[b[i].u]], pos[rfl[b[i].v]]);
}
void delr(int i) {if(b[i].op == 0) { int x = rfl[b[i].u]; answer -= a[x], cnt[x]--; AC; }swap(rfl[b[i].u], rfl[b[i].v]);swap(pos[rfl[b[i].u]], pos[rfl[b[i].v]]);
}
http://www.jsqmd.com/news/405746/

相关文章:

  • 大模型时代交互革命:小白也能秒懂,收藏必备,开启认知新纪元!
  • 保姆级实测!小白5行代码接入谷歌Gemini 3.1 Pro,复杂推理能力翻倍,速收藏!
  • JVM--16-面试题2:请详细描述 JVM 的运行时数据区
  • CF1304C
  • 技术演进中的开发沉思-371:final 关键字(中)
  • 常规正则表达式手册
  • 一款纯VF控制的变频器方案方案说明:可做0.2KW7.5KW/220V,0.2KW75KW/380V
  • python+uniapp微信小程序的连锁奶茶店甜品点单系统
  • [兰溪民间故事]董半仙的起因
  • 链板提升机哪家强?这几家制造企业值得关注,金属链板/食品链板/垂直提升机/耐高温网带/连续提升机,提升机制造商哪家好 - 品牌推荐师
  • 建议收藏|千笔,备受喜爱的降AI率平台
  • 实战指南:利用机器学习算法构建高效的保险欺诈检测系统
  • G002 强连通分量 Tarjan算法 CF999E Reachability from the Capital
  • 研究生收藏!抢手爆款的AI论文写作软件 —— 千笔·专业学术智能体
  • 原创论文:基于LSTM神经网络的金属材料机器学习本构模型研究
  • 新手也能上手 8个一键生成论文工具测评:本科生毕业论文写作全攻略
  • 基于Java的客户管理系统源码解析
  • 综述不会写?9个AI论文软件测评:本科生毕业论文写作神器推荐
  • 赶deadline必备!风靡全网的降AI率软件 —— 千笔·降AIGC助手
  • springboot高校学生学业预警系统vue
  • 互联网大厂Java求职面试实战:Spring Boot微服务与Kafka消息队列解析
  • 似曾相识
  • springboot高校食堂饭堂采购员工管理系统vue
  • 批量上传md文档中的图片
  • 书单短视频解说配音软件推荐,精选实测8款好用
  • 永辉超市卡使用及回收全攻略,解锁闲置卡券新价值 - 京顺回收
  • 横梁货架品牌哪家强?2026年这些品牌值得一看,中型货架/阁楼货架/自动化立体库货架/横梁货架,横梁货架定制厂家哪家权威 - 品牌推荐师
  • 编程的真正魔法:超越语言的关键能力
  • 船用安全阀品牌解析:2026年值得关注的厂商,船用安全阀/船用附件/船用舷侧阀/船舶配件,船用安全阀厂家选哪家 - 品牌推荐师
  • 海康Vm拿取数据的几种方式