「题解」Codeforces 1638E Colorful Operations
每次区间染色,会删除若干个颜色段,添加 \(\mathcal{O}(1)\) 个颜色段。因此颜色段总数是 \(\mathcal{O}(n+q)\).
采用平衡树(用 set 即可)维护极长连续颜色段,维护每个颜色增加值大小的 \(tag\),并用树状数组维护每个点的答案减去对应颜色的 \(tag\) 值。
Add
:直接给对应颜色的 \(tag\) 进行修改。
Color
:当删除一个颜色段时,就将其区间加上原先颜色的 \(tag\) 值;当添加一个颜色段时,就将其区间减去新颜色的 \(tag\) 值(因为新颜色原先的 \(tag\) 并没有加在这一段上,需要减去)。
Query
:输出答案即可,即树状数组维护的值加上对应颜色的 \(tag\) 值。
不难发现树状数组操作次数和颜色段次数呈线性,时间复杂度 \(\mathcal{O}((n+q)\log n)\).
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#define pb emplace_back
#define mp std::make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int,int>pii;
typedef std::pair<ll,int>pli;
typedef std::pair<ll,ll>pll;
typedef std::vector<int>vi;
typedef std::vector<ll>vll;
template<typename T>T cmax(T &x, T y){return x=x>y?x:y;}
template<typename T>T cmin(T &x, T y){return x=x<y?x:y;}
template<typename T>
T &read(T &r){
r=0;bool w=0;char ch=getchar();
while(ch<'0'||ch>'9')w=ch=='-'?1:0,ch=getchar();
while(ch>='0'&&ch<='9')r=r*10+(ch^48),ch=getchar();
return r=w?-r:r;
}
template<typename T1,typename... T2>
void read(T1 &x, T2& ...y){ read(x); read(y...); }
const int N=1000010;
inline int lowbit(int x){return x&(-x);}
int n,q;
ll tree[N],tag[N];
void modify(int x,ll v){
for(;x<=n;x+=lowbit(x))tree[x]+=v;
}
void change(int x,int y,ll v){
modify(x,v);
if(y<n)modify(y+1,-v);
}
ll query(int x){
ll s=0;
for(;x;x-=lowbit(x))s+=tree[x];
return s;
}
struct Node{
int l,r,c;
Node(int x=0,int y=0,int z=0){
l=x;r=y;c=z;
}
bool operator < (const Node &x)const{
return l<x.l;
}
};
set<Node>st;
#define IT set<Node>::iterator
IT split(int pos){
auto it=st.lower_bound(Node(pos,pos,0));
if(it!=st.end()&&(*it).l==pos)return it;
--it;
int L=(*it).l,R=(*it).r,C=(*it).c;
st.erase(it);
st.insert(Node(L,pos-1,C));
return st.insert(Node(pos,R,C)).first;
}
void assign(int l,int r,int c){
auto itr=split(r+1),itl=split(l);
auto it=split(l);
for(;it!=itr;++it)
change((*it).l,(*it).r,tag[(*it).c]);
st.erase(itl,itr);
st.insert(Node(l,r,c));
change(l,r,-tag[c]);
}
int Col(int l,int r){
auto it=st.lower_bound(Node(l,r,0));
while(it==st.end()||(!(l>=(*it).l && r<=(*it).r)))--it;
return (*it).c;
}
signed main(){
#ifdef do_while_true
freopen("data.in","r",stdin);
#endif
read(n,q);
st.insert(Node(1,n,1));
while(q--){
char ch=getchar();while(ch!='C'&&ch!='A'&&ch!='Q')ch=getchar();
if(ch=='A'){
int c,x;read(c,x);
tag[c]+=x;
}
else if(ch=='Q'){
int x;read(x);
cout << query(x)+tag[Col(x,x)] << '\n';
}
else{
int l,r,c;read(l,r,c);
assign(l,r,c);
}
}
return 0;
}