【bzoj2120】数颜色 带修莫队
数颜色
题目描述
输入格式
输出格式
样例
数据范围与提示
题解:
树套树的大佬走开。。。
线段树套平衡树,树状数组套权值线段树?
或者分块?
当然没有问题。。。,但是如果没有修改,就是莫队水题
不过幸好是单点修改,我们可以对莫对进行改造,实现区间修改
再开一个时间戳,更新和L,R类似,单点删除,增加,交换
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define MAXN 1000005 #define ll long long using namespace std; ll n,m,blo_num,col[MAXN],block[MAXN],l=1,r=0,sum[MAXN],ans=0,t=0; ll q_sum=0,c_sum=0,out[MAXN]; struct node1{ ll l,r,id,t; }ask[MAXN]; struct node2{ ll pos,col; }change[MAXN]; bool cmp(const node1 x,const node1 y){ return x.l/blo_num==y.l/blo_num?(x.r/blo_num==y.r/blo_num?x.t<y.t:x.r<y.r):x.l<y.l; } void add(ll i){ if(!sum[i]) ans++; sum[i]++; } void del(ll i){ sum[i]--; if(!sum[i]) ans--; } int main(){ scanf("%lld%lld",&n,&m); blo_num=(ll)pow(n,2.0/3.0); for(ll i=1;i<=n;i++){ scanf("%lld",&col[i]); block[i]=i/blo_num; } for(ll i=1;i<=m;i++){ char Q[5]; scanf("%s",Q); if(Q[0]=='Q'){ q_sum++; scanf("%lld%lld",&ask[q_sum].l,&ask[q_sum].r); ask[q_sum].id=q_sum; ask[q_sum].t=c_sum; } else{ c_sum++; scanf("%lld%lld",&change[c_sum].pos,&change[c_sum].col); } } sort(ask+1,ask+q_sum+1,cmp); for(ll i=1;i<=q_sum;i++){ while(l<ask[i].l) del(col[l++]); while(l>ask[i].l) add(col[--l]); while(r<ask[i].r) add(col[++r]); while(r>ask[i].r) del(col[r--]); while(t<ask[i].t){ t++; if(ask[i].l<=change[t].pos&&change[t].pos<=ask[i].r){ del(col[change[t].pos]); add(change[t].col); } swap(col[change[t].pos],change[t].col); } while(t>ask[i].t){ if(ask[i].l<=change[t].pos&&change[t].pos<=ask[i].r){ del(col[change[t].pos]); add(change[t].col); } swap(col[change[t].pos],change[t].col); t--; } out[ask[i].id]=ans; } for(ll i=1;i<=q_sum;i++) printf("%lld\n",out[i]); return 0; }