[bzoj2120]数颜色

  TAT

  如果只维护画笔的颜色的话显然解决不了查询= =所以考虑维护别的东西。。

  令pre[i]表示第pre[i]支画笔颜色同笔i相同且离得最近(pre[i]<i)。对于区间[l,r]中,如果某一支笔x的pre值<l,那么这支笔的颜色是当前区间里第一个出现的,答案+1.

  然后我就脑残写了个线段树套treap。。。。。。

  外层线段树表示区间,内层按pre值建treap。查询的时候在线段树上拆成一个个区间,然后在treap里查询一下pre值比l小的笔的数目。

  因为修改时会改变pre值。。所以我再建了个treap'。。。。。。每种颜色一颗treap',treap'里以笔所在位置为关键字。

  所以每次修改某支画笔的颜色的时候,找出它原本的前驱后继改改改,再找出它颜色改变后的前驱后继改改改TAT。。

  其实就是维护一下前驱。。每次修改最多改变三支画笔的前驱(自己,原本的后继,颜色改变后的后继)。

  最后码了快5k。。。sxbk。。。其实正常做法不是分块暴力吗TAT

  本来做好被分块艹的准备了。。结果O(nlog²n)竟然战胜了O(n^1.5)。。。感人肺腑

  值得吐槽的是我已经连续若干次因为treap的更新写错而调了1h+了。。。。。。。。。。。

  另。。全部加inline后就从#6爬到#2了= =..inline大法好代码长度哭了

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn=10023;
  7 struct zs{
  8     int num,id;
  9 }a[maxn<<1];
 10 struct ask{
 11     int l,r;bool id;
 12 }q[maxn];
 13 int i,j,n,m,cnt;
 14 int b[maxn],c[maxn<<1],pre[maxn],last[maxn<<1];
 15 int l[maxn*18],r[maxn*18],rnd[maxn*18],sz[maxn*18],w[maxn*18],num[maxn*18],tot;
 16 int rt[33233],size;
 17  
 18 int ra;char rx;
 19 inline int read(){
 20     rx=getchar(),ra=0;
 21     while(rx<'0'||rx>'9')rx=getchar();
 22     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
 23 }
 24  
 25 inline void lturn(int &x,int R){
 26     r[x]=l[R],l[R]=x,sz[R]=sz[x],sz[x]=sz[l[x]]+w[x]+sz[r[x]],x=R;
 27 }
 28 inline void rturn(int &x,int L){
 29     l[x]=r[L],r[L]=x,sz[L]=sz[x],sz[x]=sz[l[x]]+w[x]+sz[r[x]],x=L;
 30 }
 31 inline void ins(int &x,int v){
 32     if(!x){x=++tot,rnd[x]=rand(),sz[x]=w[x]=1,num[x]=v;return;}
 33     ++sz[x];
 34     if(num[x]==v)w[x]++;else
 35     if(v<num[x]){
 36         ins(l[x],v);
 37         if(rnd[l[x]]<rnd[x])rturn(x,l[x]);
 38     }else{
 39         ins(r[x],v);
 40         if(rnd[r[x]]<rnd[x])lturn(x,r[x]);
 41     }
 42 }
 43 inline void del(int &x,int v){
 44     if(num[x]==v){
 45         if(w[x]>1)--w[x],--sz[x];else
 46         if(!(l[x]&&r[x]))x=l[x]|r[x];else
 47         if(rnd[l[x]]<rnd[r[x]])rturn(x,l[x]),del(x,v);
 48             else lturn(x,r[x]),del(x,v);
 49     }else if(v<num[x]) --sz[x],del(l[x],v);
 50     else --sz[x],del(r[x],v);
 51 }
 52 inline int get(int x,int v){
 53     if(!x)return 0;
 54     if(v<num[x])return get(l[x],v);else
 55     if(v==num[x])return sz[l[x]];else
 56     return get(r[x],v)+w[x]+sz[l[x]];
 57 }
 58 inline int query(int l,int r){
 59     if(l>r)swap(l,r);
 60     if(l==r)return 1;
 61     int l1=l;l+=size,r+=size;int sum=get(rt[l],l1)+get(rt[r],l1);
 62     for(;l^r^1;l>>=1,r>>=1){
 63         if(!(l&1))sum+=get(rt[l^1],l1);
 64         if(r&1)sum+=get(rt[r^1],l1);
 65     }
 66     return sum;
 67 }
 68 //---------------------------------------------------------------
 69  
 70 int Tl[maxn<<1],Tr[maxn<<1],Trnd[maxn<<1],Tnum[maxn<<1],Trt[maxn<<1],Ttot;
 71 int Tpre,Taft;
 72 inline void Tlturn(int &x,int R){
 73     Tr[x]=Tl[R],Tl[R]=x,x=R;
 74 }
 75 inline void Trturn(int &x,int L){
 76     Tl[x]=Tr[L],Tr[L]=x,x=L;
 77 }
 78 inline void Tins(int &x,int v){
 79     if(!x){x=++Ttot,Trnd[x]=rand(),Tnum[x]=v;return;}
 80     if(v<Tnum[x]){
 81         Tins(Tl[x],v);
 82         if(Trnd[Tl[x]]<Trnd[x])Trturn(x,Tl[x]);
 83     }else{
 84         Tins(Tr[x],v);
 85         if(Trnd[Tr[x]]<Trnd[x])Tlturn(x,Tr[x]);
 86     }
 87 }
 88 inline void Tdel(int &x,int v){
 89     if(Tnum[x]==v){
 90         if(!(Tl[x]&&Tr[x]))x=Tl[x]|Tr[x];else
 91         if(Trnd[Tl[x]]<Trnd[Tr[x]])Trturn(x,Tl[x]),Tdel(x,v);
 92             else Tlturn(x,Tr[x]),Tdel(x,v);
 93     }else if(v<Tnum[x]) Tdel(Tl[x],v);
 94     else Tdel(Tr[x],v);
 95 }
 96 inline void getpre(int x,int v){
 97     if(!x)return;
 98     if(Tnum[x]<v)Tpre=Tnum[x],getpre(Tr[x],v);else
 99     getpre(Tl[x],v);
100 }
101 inline void getaft(int x,int v){
102     if(!x)return;
103     if(Tnum[x]>v)Taft=Tnum[x],getaft(Tl[x],v);else
104     getaft(Tr[x],v);
105 }
106  
107 bool cmp(zs a,zs b){return a.num<b.num;}
108 int main(){
109     n=read(),m=read();char id;
110     for(i=1;i<=n;i++)a[i].id=i,a[i].num=read();int n1=n;
111     for(i=1;i<=m;i++){
112         for(id=getchar();id<'A'||id>'Z';id=getchar());
113         q[i].id=(id=='R');q[i].l=read(),q[i].r=read();
114         if(q[i].id)a[++n1].id=i+n,a[n1].num=q[i].r;
115     }
116     sort(a+1,a+1+n1,cmp);cnt=0;
117     for(i=1;i<=n1;i++){
118         if(a[i].num!=a[i-1].num||i==1)c[++cnt]=a[i].num;
119         if(a[i].id<=n)b[a[i].id]=cnt;else q[a[i].id-n].r=cnt;
120     }
121      
122     for(size=1;size<n;size<<=1); size--;
123     for(i=1;i<=n;i++){
124         pre[i]=last[b[i]],last[b[i]]=i;
125         for(j=i+size;j;j>>=1)ins(rt[j],pre[i]);
126         Tins(Trt[b[i]],i);
127     }
128     for(i=1;i<=m;i++)
129         if(!q[i].id)
130             printf("%d
",query(q[i].l,q[i].r));
131         else if(b[q[i].l]!=q[i].r){
132             Tpre=0,getpre(Trt[b[q[i].l]],q[i].l),Taft=n+1,getaft(Trt[b[q[i].l]],q[i].l);
133              
134             if(Taft<=n){
135                 for(j=Taft+size;j;j>>=1)del(rt[j],pre[Taft]),ins(rt[j],Tpre);
136                 pre[Taft]=Tpre;
137             }
138                          
139             Tpre=0,getpre(Trt[q[i].r],q[i].l),Taft=n+1,getaft(Trt[q[i].r],q[i].l);
140             if(Taft<=n){
141                 for(j=Taft+size;j;j>>=1)del(rt[j],pre[Taft]),ins(rt[j],q[i].l);
142                 pre[Taft]=q[i].l;
143             }
144             for(j=q[i].l+size;j;j>>=1)del(rt[j],pre[q[i].l]),ins(rt[j],Tpre);
145             pre[q[i].l]=Tpre,
146              
147             Tdel(Trt[b[q[i].l]],q[i].l),b[q[i].l]=q[i].r,Tins(Trt[b[q[i].l]],q[i].l);
148         }
149     return 0;
150 }
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5134575.html