1. 程式人生 > >bzoj2120: 數顏色(BIT套主席樹+set/分塊)

bzoj2120: 數顏色(BIT套主席樹+set/分塊)

iter string ... 區間 stream else del amp ast

  帶修改的 HH的項鏈。

  帶修改考慮用BIT套主席樹,查區間裏有幾個不同的數用a[i]上次出現的位置pre[i]<l的數有幾個來算就好了。

  考慮怎麽修改。修改i的時候,我們需要改變i同顏色的後繼的pre,加入新的顏色,並且找到i在新顏色中的前驅後繼,更改自己的pre和在新顏色中後繼的pre,於是用一個set來維護每種顏色的前驅後繼就好了。

技術分享
#include<iostream> 
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath> 
#include
<algorithm> #include<set> using namespace std; const int maxn=500010,inf=1e9; struct poi{int sum,lt,rt;}tree[maxn<<2]; int n,m,sz,N,x,delta; int a[maxn],b[maxn],q1[maxn],q2[maxn],root[maxn],pos[maxn]; char ch[maxn][1]; set<int>s[maxn]; set<int>::iterator pre,it,last; inline
void read(int &k) { int f=1;k=0;char c=getchar(); while(c<0||c>9)c==-&&(f=-1),c=getchar(); while(c<=9&&c>=0)k=k*10+c-0,c=getchar(); k*=f; } inline int lowbit(int x){return x&-x;} void update(int &x,int l,int r,int cx,int delta) { tree[
++sz]=tree[x];tree[sz].sum+=delta;x=sz; if(l==r)return; int mid=(l+r)>>1; if(cx<=mid)update(tree[x].lt,l,mid,cx,delta); else update(tree[x].rt,mid+1,r,cx,delta); } int query(int x,int l,int r,int cl,int cr) { if(cl<=l&&r<=cr)return tree[x].sum; int mid=(l+r)>>1,ret=0; if(cl<=mid)ret+=query(tree[x].lt,l,mid,cl,cr); if(cr>mid)ret+=query(tree[x].rt,mid+1,r,cl,cr); return ret; } int main() { read(n);read(m); for(int i=1;i<=n;i++)read(a[i]),b[++N]=a[i]; for(int i=1;i<=m;i++) { scanf("%s",ch[i]);read(q1[i]);read(q2[i]); if(ch[i][0]==R)b[++N]=q2[i]; } sort(b+1,b+1+N);N=unique(b+1,b+1+N)-b-1; for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+N,a[i])-b; for(int i=1;i<=n;i++) { for(int j=i;j<=n;j+=lowbit(j)) update(root[j],0,N,pos[a[i]],1); s[a[i]].insert(i);pos[a[i]]=i; } for(int i=1;i<=N;i++)s[i].insert(0); for(int i=1;i<=m;i++) { if(ch[i][0]==Q) { int ans=0; for(int j=q1[i]-1;j;j-=lowbit(j))ans-=query(root[j],0,N,0,q1[i]-1); for(int j=q2[i];j;j-=lowbit(j))ans+=query(root[j],0,N,0,q1[i]-1); printf("%d\n",ans); } else { pre=it=last=s[a[q1[i]]].find(q1[i]);pre--;last++; if(last!=s[a[q1[i]]].end()) { for(int j=*last;j<=n;j+=lowbit(j))update(root[j],0,N,q1[i],-1); for(int j=*last;j<=n;j+=lowbit(j))update(root[j],0,N,*pre,1); } q2[i]=lower_bound(b+1,b+1+N,q2[i])-b; for(int j=q1[i];j<=n;j+=lowbit(j))update(root[j],0,N,*pre,-1); s[a[q1[i]]].erase(it);a[q1[i]]=q2[i];s[a[q1[i]]].insert(q1[i]); pre=last=s[a[q1[i]]].find(q1[i]);pre--;last++; for(int j=q1[i];j<=n;j+=lowbit(j))update(root[j],0,N,*pre,1); if(last!=s[a[q1[i]]].end()) { for(int j=*last;j<=n;j+=lowbit(j))update(root[j],0,N,*pre,-1); for(int j=*last;j<=n;j+=lowbit(j))update(root[j],0,N,q1[i],1); } } } }
View Code

  分塊的做法等會補...

bzoj2120: 數顏色(BIT套主席樹+set/分塊)