题目链接

我们给每个连通块图上一种颜色。不同的连通块涂不同的颜色。

首先,我们定义\(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集训】货币的更多相关文章

  1. 2018.7.16 题解 2018暑假集训之Roads-roads

    题面描述 有标号为1--n的城市与单行道相连.对于每条道路有两个与之相关的参数:道路的长度以及需要支付的费用(用硬币的数量表示) 鲍勃和爱丽丝曾经生活在城市1.在注意到爱丽丝在他们喜欢玩的卡牌游戏中作 ...

  2. AtCoder Grand Contest 017 题解

    A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...

  3. [NOIP提高组2018]货币系统

    [TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...

  4. hdu 1217(Floyed)

    Arbitrage Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

  5. 【BZOJ4928】第二题 树hash+倍增

    [BZOJ4928]第二题 Description 对于一棵有根树,定义一个点u的k-子树为u的子树中距离u不超过k的部分. 注意,假如u的子树中不存在距离u为k的点,则u的k-子树是不存在的. 定义 ...

  6. 【BZOJ4930】棋盘 拆边费用流

    [BZOJ4930]棋盘 Description 给定一个n×n的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置(x,y),(u,v)能互相攻击当前仅 当满足以下两个条件: 1:x=u或y ...

  7. OI总结

    当下考的钟声叮当响起,该走了,一年半的OI竞赛就此结束 留下了很多遗憾.也拥有过一段美好的竞赛生活 结识了一群优秀的OI战友,一起进步一起开心一起忧愁,但这一切的一切都将在今晚变成过去式,CSp的好与 ...

  8. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

  9. 【某集训题解】【DAY 2 T3】与非

    题目描述 作为一名新世纪共产主义的接班人,你认识到了资本主义的软弱性与妥协性,决定全面根除资本主义,跑步迈入共产主义.但是当你即将跨入共产主义大门的时候,遇到了万恶的资本家留下的与非电路封印,经过千辛 ...

随机推荐

  1. 【PAT甲级】1058 A+B in Hogwarts (20 分)

    题意: 输入两组,每组三个非负整数A,B,C(A<=1e7,B<17,C<29),输出相加的和.(类似个位上29进制,十位上17进制运算) AAAAAccepted code: #d ...

  2. thymeleaf模板引擎简介

    一:thymeleaf 学习笔记---http://www.blogjava.net/bjwulin/articles/395185.html thymeleaf是一个支持html原型的自然引擎,它在 ...

  3. redhat 7.6 流量监控命令、软件(1) ethstatus

    1. 查看1个月内流量,只保留一个月的流量 命令: sar   -n  DEV   -f    /var/log/sa/sa26 RX代表进来的流量,TX代表出去的流量 2.安装查看实时流量软件eth ...

  4. RuntimeError: cuda runtime error (10) : invalid device ordinal

    This is caused by the unmatching of gpu device number when loading a saved model. torch.load('my_fil ...

  5. Python压缩文件/文件夹

    [Python压缩文件夹]导入“zipfile”模块 def zip_ya(startdir,file_news): startdir = ".\\123" #要压缩的文件夹路径 ...

  6. sourceTree的忽略文件

    在没有导入项目之前,就要把忽略配置好: *~ .DS_Store xcuserdata

  7. 关于自学java的内容及感受

    这周自学了关于java输入的知识:java输入的方法与c++和c有些不同,他需要在开头加一个import连接系统的包,才能进行输入语句的编写. 自己编写了一点简单的输入的程序: package mod ...

  8. mysql之魔鬼训练营

    普通 + 中等 难度练习题 测试数据: --建表 --学生表 CREATE TABLE `Student`( `s_id` VARCHAR(20), `s_name` VARCHAR(20) NOT ...

  9. 各颜色LED压降

    一下是参考1.直插LED压降红:2.0-2.2V黄:1.8-2.0V绿:3.0-3.2V 额定电流约20mA.2.贴片LED压降红:1.82-1.88V,电流5-8mA绿:1.75-1.82V,3-5 ...

  10. 十八 Spring的JDBC模板:引入外部属性文件

    配置外部属性文件 配置文件里引入属性文件,两种方式 第一种: 第二种: 引入属性文件的值: 测试: <?xml version="1.0" encoding="UT ...