BZOJ2141: 排队
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2141
分块加树状数组。
离散化之后,每一个块建一个树状数组。交换x,y,与x左边的数和y右边的数无关,只需处理>x,<y的数。
话说还可以用树套树来写,不过常数太大,比分块加树状数组慢。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #define inf 1<<30 7 #define maxn 20005 8 using namespace std; 9 int n,m,nn,tot,ans,a[maxn],t[205][maxn]; 10 struct fuck{int x,id;}c[maxn]; 11 int read(){ 12 int x=0,f=1; char ch; 13 for(ch=getchar();ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1; 14 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 15 return x*f; 16 } 17 bool comp(fuck a,fuck b){return a.x<b.x;} 18 int p(int x){return (x-1)/nn+1;} 19 void change(int f,int x,int y){for(int i=x;i<=tot;i+=i&-i) t[f][i]+=y;} 20 int query(int f,int x){int y=0;for(int i=x;i;i-=i&-i) y+=t[f][i];return y;} 21 int main(){ 22 n=read(); nn=sqrt(n); 23 for(int i=1;i<=n;i++) c[i].x=read(),c[i].id=i; 24 sort(c+1,c+n+1,comp); 25 for(int i=1;i<=n;i++){ 26 if(c[i].x!=c[i-1].x) ++tot; 27 a[c[i].id]=tot; 28 } 29 for(int i=n;i;i--){ 30 ans+=query(0,a[i]-1); 31 change(0,a[i],1); 32 } 33 printf("%d\n",ans); 34 for(int i=1;i<=n;i++) change(p(i),a[i],1); 35 m=read(); 36 int x,y; 37 while(m--){ 38 x=read(); y=read(); if(x>y) swap(x,y); 39 for(int i=p(x)+1;i<p(y);i++){ 40 ans-=query(i,a[x]-1); ans+=query(i,tot)-query(i,a[x]); 41 ans-=query(i,tot)-query(i,a[y]); ans+=query(i,a[y]-1); 42 } 43 for(int i=x+1;p(i)==p(x)&&i<y;i++){ 44 if(a[i]<a[x]) ans--; if(a[i]>a[x]) ans++; 45 if(a[i]<a[y]) ans++; if(a[i]>a[y]) ans--; 46 } 47 if(p(x)!=p(y)) 48 for(int i=y-1;p(i)==p(y);i--){ 49 if(a[i]<a[x]) ans--; if(a[i]>a[x]) ans++; 50 if(a[i]<a[y]) ans++; if(a[i]>a[y]) ans--; 51 } 52 if(a[x]<a[y]) ans++; if(a[x]>a[y]) ans--; 53 change(p(x),a[x],-1); change(p(x),a[y],1); 54 change(p(y),a[y],-1); change(p(y),a[x],1); 55 swap(a[x],a[y]); 56 printf("%d\n",ans); 57 } 58 return 0; 59 }