做法
感谢 @newbiegcz 的指导
做法和题解是一样的,然而英文太烂没有看懂。看了cz_xuyixuan的才看懂。后面维护方法和他略有不同
要找分界点:分段后,每段包含其中的所有颜色的所有出现位置
首先:一个颜色只考虑其两端 [ L i , R i ] [L_i,R_i] [Li,Ri],分界点不能在这个区间中间。每个颜色会删去在 [ L i , R i ) [L_i,R_i) [Li,Ri)的分界点,剩下的就是合法分界点(被删除次数为 0 0 0的位置后)
分出每一段后,求出每段颜色出现次数最大值, 答 案 = n − 每 段 最 大 值 求 和 答案 = n - 每段最大值求和 答案=n−每段最大值求和
带修改的情况用线段树维护这个覆盖次数(被删除的次数),为 0 0 0则是一个合法的分界点。而注意到在顶层n后面一定是一个合法的分界点。故只需要记录最小值,默认每一层的最小值位置后就是合法分界点。合并的时候讨论一下即可这样就只用一个线段树搞定了!(这种做法学习自@newbiegcz的代码)
对于修改,经典的做法是看成对两种颜色的删除和插入。修改一种颜色时,也是先在线段树中删除这种颜色,再修改,再插入。这样非常好写!
#include<bits/stdc++.h>
using namespace std;
#define PB push_back
#define lowbit(x) (x&(-x))
#define MP make_pair
#define fi first
#define se second
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define rep(i,l,r) for (int i = l ; i <= r ; i++)
#define down(i,r,l) for (int i = r ; i >= l ; i--)
#define fore(i,x) for (int i = head[x] ; i ; i = e[i].next)
#define SZ(v) (int)v.size()
typedef long