题解 zr1212 【20WC集训】货币
我们给每个连通块图上一种颜色。不同的连通块涂不同的颜色。
首先,我们定义\(f_r\)表示:使\([l,r]\)包括\([1,r]\)里所有颜色的最大的\(l\)。
然后我维护一个变量\(pos\),表示从\(pos\)到\(n\)的这些点\(i\)(\(\forall i\in[pos,n]\)),\([1,i]\)中包含了当前所有的颜色。容易发现这个条件就等价于\([1,pos]\)中包含了所有颜色。对每次操作显然\(pos\)是单调减的,所以就很好维护。在并查集时,令每个连通块的根,也就是fa[x]==x
的那个节点,是这个连通块里的最小位置。即在合并时:fa[max(x,y)]=min(x,y)
。这样我们就可以这么维护\(pos\):
//初始化:
pos=n;
//每次询问时:
while(pos>1&&get_father(pos)!=pos)pos--;
有了\(pos\)之后,一次询问的答案就是对\([pos,n]\)这段的每个\(i\),求\(i-f_i+1\)的最小值。这就是\(f_i\)的作用。
我们定于\(\text{next}_i\)表示\(i\)后面第一个和\(i\)同色的位置。则容易发现\(\displaystyle f_i=\min_{\text{next}_j>i}\{j\}\)。其含义是:对于每一种颜色,你取它在\(i\)前面最后一次出现的位置,然后对这些位置取\(\min\),得到的就是使得\([l,i]\)包含所有\(i\)前面的颜色的最大的\(l\)了。如果已知了\(\text{next}\)数组,我们用线段树维护\(\text{next}\)的区间最大值,则某个点\(i\)的\(f_i\)可以通过线段树上二分,在\(O(\log n)\)的时间内求出。
线段树上二分程序片段:
int query(int p,int l,int r,int pos){
if(l==r){
assert(mx[p]>pos);
return l;
}
int mid=(l+r)>>1;
if(mx[p<<1]>pos)return query(p<<1,l,mid,pos);
else return query(p<<1|1,mid+1,r,pos);
}
回到问题,首先我们肯定要启发式合并,这样我们就有机会暴力更改集合里的每个点,便于我们维护\(f\)。
对于一个点\(u\),如果:
\(u\)的颜色变了;
或\(u\)左边新插入了一个颜色和\(u\)不一样的点;
或\(u\)右边新插入了一个颜色和\(u\)不一样的点;
那么原本一些位置的\(f\)值就会变化。具体哪些位置会变呢,我们发现只有\(f_i=u\)的这些\(i\)会变。又因为\(f\)是单调递增的,所以\(f_i=u\)的\(i\)一定在一段连续的区间。
证明:只有原本\(f_i=u\)的这些\(i\)的\(f\)值会变。
考虑\(f_i<u\)时,这样的\(f_i\)瓶颈不在\(u\),也就是说它在取\(\min\)时会取到一个比\(u\)还小的位置。所以这样的\(f_i\)显然不会变。
\(f_i>u\)时,说明\(u\)后面还有一个和\(u\)同色的点在\(i\)之前,所以\(u\)就和\(i\)无关了。
现在我们考虑求出\(f_i=u\)的\(i\)的区间。我们用另一棵线段树,维护\(f\)的区间最大值、区间最小值。这样就可以线段树上二分出这个区间。
考虑这段区间\([l,r]\),它在我们进行操作前\(f\)值是相等的,操作后它会分裂成若干段区间。我也不知道具体会分裂成几段。
但是!
最多只有\(2\)段会和前后的合并起来。(这里的合并是指变成\(f\)值相同的连续段,这只是我们证明复杂度用的,在代码里并不需要真的合并)。而整个序列最多只有\(n\)段\(f\)值,每次最多只会减小\(2\)段,因此增加的段数总量不超过\(n+2m\),是\(O(n)\)级别的!
这样我们就可以一段一段暴力跳了。
最后的问题是对于一个\(l\),如何跳到最靠后的一个和它\(f\)值相等的\(r\)(这里指修改后的\(f\)值)。
首先根据最开始的讨论,我们可以求出\(l\)在修改后的\(f\)值,我们记为\(pre\)。则\(l\)之后的第一个和\(l\)的\(f\)值不同的地方在\(\text{next}_{pre}\)。
证明:
对于每个\(i\in[l,\text{next}_{pre})\),\(f_i\)首先不可能小于\(f_l\),因为这样不符合\(\displaystyle pre=\min_{\text{next}_j>l}\{j\}\)的性质。
然后\(f_i\)也不可能\(>pre\),因为\(i<\text{next}_{pre}\),所以取\(\min\)时就一定会取到\(pre\)。
因此\(\forall i\in[l,\text{next}_{pre}),f_i=pre\)。
又因为\(i\geq \text{next}_{pre}\)时取\(\min\)一定不会取到\(pre\)了,所以\(f_i>pre\)。
综上,\(l\)之后的第一个和\(l\)的\(f\)值不同的地方在\(\text{next}_{pre}\)。
于是我们的操作就是:
对每个被更新的\(u\),找出对应的\([l,r]\);
求出\(pre=f_l\),对\([l,\min(\text{next}_{pre}-1,r)]\)区间的\(f\)值进行区间覆盖(全部改成\(f_l\));
令\(l=\text{next}_{pre}\),重复第二步,直到\(l>r\)时结束。
具体实现时我们把所有要处理的\(u\)压到一个vector
里即可。
因为是启发式合并的基础上用线段树修改,所以复杂度\(O(n\log^2 n)\)。
题解 zr1212 【20WC集训】货币的更多相关文章
- 2018.7.16 题解 2018暑假集训之Roads-roads
题面描述 有标号为1--n的城市与单行道相连.对于每条道路有两个与之相关的参数:道路的长度以及需要支付的费用(用硬币的数量表示) 鲍勃和爱丽丝曾经生活在城市1.在注意到爱丽丝在他们喜欢玩的卡牌游戏中作 ...
- AtCoder Grand Contest 017 题解
A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...
- [NOIP提高组2018]货币系统
[TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...
- hdu 1217(Floyed)
Arbitrage Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- 【BZOJ4928】第二题 树hash+倍增
[BZOJ4928]第二题 Description 对于一棵有根树,定义一个点u的k-子树为u的子树中距离u不超过k的部分. 注意,假如u的子树中不存在距离u为k的点,则u的k-子树是不存在的. 定义 ...
- 【BZOJ4930】棋盘 拆边费用流
[BZOJ4930]棋盘 Description 给定一个n×n的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置(x,y),(u,v)能互相攻击当前仅 当满足以下两个条件: 1:x=u或y ...
- OI总结
当下考的钟声叮当响起,该走了,一年半的OI竞赛就此结束 留下了很多遗憾.也拥有过一段美好的竞赛生活 结识了一群优秀的OI战友,一起进步一起开心一起忧愁,但这一切的一切都将在今晚变成过去式,CSp的好与 ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- 【某集训题解】【DAY 2 T3】与非
题目描述 作为一名新世纪共产主义的接班人,你认识到了资本主义的软弱性与妥协性,决定全面根除资本主义,跑步迈入共产主义.但是当你即将跨入共产主义大门的时候,遇到了万恶的资本家留下的与非电路封印,经过千辛 ...
随机推荐
- linux的压力测试工具
只能用于http的测试工具: ab: 安装方法:yum install httpd-tools -y 使用:ab -c 1000 -n 10000 + ip -c 为并发数,-n ...
- nyoj 24
素数距离问题 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度.如果左右有等距离长度 ...
- windows网络编程-C语言实现简单的TCP协议聊天
TCP/IP协议(面向连接协议)类似于打电话时,对方一定在手机附近并且此刻都在和对方进行通话.一定保证双方都在线,才能进行数据传输.UDP/IP协议(无连接协议)就像邮箱,不保证对方一定在等你邮件且对 ...
- 安装插件报错error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++
起因:学到多线程greenlet模块时,greenlet模块死活装不上,以为pycharm坏掉了,浪费了一下午. #pip3 install greenlet from greenlet import ...
- jackson处理日期异常
原 jackson处理日期异常 2018年01月09日 10:50:19 阅读数:70 1.异常信息 2.原因 默认情况下,fasterxml json只支持几种format,但是肯定不支持" ...
- ShellCode模板
前言 在上一篇文章上使用到的添加用户的shellcode是怎么得到的呢? 先来拆分一下汇编的功能 ;寻找kernel32.dll的基地址 xor ecx,ecx mov eax,dword ptr f ...
- build hadoop, spark, hbase cluster
1,something: 1,arc land 506 git branch 507 git status 508 git reset multicloud/qcloud/cluster_man ...
- elk安装2.0版本,自己总结,比较细致 es单机的安装
用root用户会报错,版本6之前还是可以用root用户启动的,针对es的保护,数据的一些问题,6之后就不允许了. 启动成功 下面验证一下 可以直接用浏览器访问,接受http访问 配置,因为没有暴露端 ...
- python 基础文件操作
实时刷新到硬盘里 f= open('hh','w',encoding='utf8') f.write('gyftyftft') f.write('hghgh\njkkjk') f.flush()#实时 ...
- 树莓派安装nextcloud、Seafile
参考博文:http://bbs.eeworld.com.cn/thread-505579-1-1.html http://blog.sina.com.cn/s/blog_6f55d8210102xia ...