【bzoj2141】排队 [国家集训队2011]排队(树套树)
题目描述
排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。
红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足i<j且hi>hj的(i,j)数量。
幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。
题解
新技能get
树状数组+动态开点线段树
具体看代码(因为我讲不来)
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 const int N=20005; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 inline int read(){ 10 #define num ch-'0' 11 char ch;bool flag=0;int res; 12 while(!isdigit(ch=getc())) 13 (ch=='-')&&(flag=true); 14 for(res=num;isdigit(ch=getc());res=res*10+num); 15 (flag)&&(res=-res); 16 #undef num 17 return res; 18 } 19 char sr[1<<21],z[20];int C=-1,Z; 20 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 21 inline void print(int x){ 22 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 23 while(z[++Z]=x%10+48,x/=10); 24 while(sr[++C]=z[Z],--Z);sr[++C]='\n'; 25 } 26 struct node{ 27 int v,id; 28 inline bool operator <(const node &b)const{return v<b.v;} 29 }a[N]; 30 int n,m,x,y,tot,ans,b[N],c[N]; 31 inline void add(int x){ 32 for(;x<=n;x+=x&-x) ++c[x]; 33 } 34 inline int sum(int x){ 35 int res=0; 36 for(;x;x-=x&-x) res+=c[x]; 37 return res; 38 } 39 int cnt,rt[N],v[N*400],L[N*400],R[N*400]; 40 void insert(int &u,int l,int r,int x,int k){ 41 if(!u) u=++cnt;v[u]+=k; 42 if(l==r) return;int mid=l+r>>1; 43 if(x<=mid) insert(L[u],l,mid,x,k); 44 else insert(R[u],mid+1,r,x,k); 45 } 46 void push(int x,int y,int k){ 47 for(;x<=n;x+=x&-x) insert(rt[x],1,n,y,k); 48 } 49 int Query(int u,int l,int r,int ql,int qr){ 50 if(!u) return 0; 51 if(ql<=l&&qr>=r) return v[u]; 52 int mid=l+r>>1; 53 int res=0; 54 if(ql<=mid) res+=Query(L[u],l,mid,ql,qr); 55 if(qr>mid) res+=Query(R[u],mid+1,r,ql,qr); 56 return res; 57 } 58 int query(int l,int r,int ql,int qr){ 59 if(l>r||ql>qr) return 0; 60 int sum=0;--l; 61 for(;r;r-=r&-r) sum+=Query(rt[r],1,n,ql,qr); 62 for(;l;l-=l&-l) sum-=Query(rt[l],1,n,ql,qr); 63 return sum; 64 } 65 int main(){ 66 //freopen("testdata.in","r",stdin); 67 n=read(); 68 for(int i=1;i<=n;++i) a[i]=(node){read(),i}; 69 sort(a+1,a+1+n); 70 for(int i=1;i<=n;++i){ 71 if(a[i].v!=a[i-1].v) ++tot; 72 b[a[i].id]=tot; 73 } 74 for(int i=n;i;--i) ans+=sum(b[i]-1),add(b[i]); 75 for(int i=1;i<=n;++i) push(i,b[i],1); 76 m=read(),print(ans); 77 while(m--){ 78 int x=read(),y=read(); 79 if(x>y) swap(x,y); 80 ans+=query(x+1,y-1,1,b[y]-1); 81 ans-=query(x+1,y-1,b[y]+1,n); 82 ans+=query(x+1,y-1,b[x]+1,n); 83 ans-=query(x+1,y-1,1,b[x]-1); 84 if(b[x]>b[y]) --ans; 85 if(b[x]<b[y]) ++ans; 86 push(x,b[x],-1),push(y,b[y],-1); 87 push(y,b[x],1),push(x,b[y],1); 88 swap(b[x],b[y]); 89 print(ans); 90 } 91 Ot(); 92 return 0; 93 }
深深地明白自己的弱小