bzoj2141: 排队
诶这这这这怎么又是树状数组和逆序对(快要被虐哭了55555)
强行分块。。。
我们先开block个权值树状数组,把每个块的值插进去,块里面的直接算,外面的靠树状数组
if sum ++ -- 好烦。。
然而对拍是个好东西。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int s[150][21000]; int lowbit(int x){return x&-x;} void change(int x,int w,int k) { while(x<=20100) { s[w][x]+=k; x+=lowbit(x); } } int getsum(int x,int w) { int ret=0; while(x>0) { ret+=s[w][x]; x-=lowbit(x); } return ret; } //----------bit------------------------ int a[21000]; int lslen,ls[21000]; int block,st[21000]; int main() { freopen("data.in","r",stdin); freopen("1.out","w",stdout); int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),ls[++lslen]=a[i]; sort(ls+1,ls+lslen+1); lslen=unique(ls+1,ls+lslen+1)-ls-1; for(int i=1;i<=n;i++) a[i]=lower_bound(ls+1,ls+lslen+1,a[i])-ls; int sum=0; for(int i=1;i<=n;i++) { sum+=(i-1-getsum(a[i],1)); change(a[i],1,1); } memset(s[1],0,sizeof(s[1])); printf("%d\n",sum); //--------sc&&LSH&&初始逆序对数----------------- block=int(sqrt(double(n+1))); for(int i=1;i<=n;i++) { st[i]=(i-1)/block+1; change(a[i],st[i],1); } int Q,x,y; scanf("%d",&Q); while(Q--) { scanf("%d%d",&x,&y); if(x>y)swap(x,y); if(a[x]>a[y])sum--; if(a[x]<a[y])sum++; if(st[x]==st[y]) { for(int i=x+1;i<=y-1;i++) { if(a[x]>a[i])sum--; if(a[x]<a[i])sum++; if(a[y]>a[i])sum++; if(a[y]<a[i])sum--; } swap(a[x],a[y]); } else { for(int i=x+1;i<=st[x]*block;i++) { if(a[x]>a[i])sum--; if(a[x]<a[i])sum++; if(a[y]>a[i])sum++; if(a[y]<a[i])sum--; } for(int i=(st[y]-1)*block+1;i<=y-1;i++) { if(a[x]<a[i])sum++; if(a[x]>a[i])sum--; if(a[y]<a[i])sum--; if(a[y]>a[i])sum++; } for(int i=st[x]+1;i<=st[y]-1;i++) { sum-=getsum(a[x]-1,i); sum+=block-getsum(a[x],i); sum+=getsum(a[y]-1,i); sum-=block-getsum(a[y],i); } change(a[x],st[x],-1); change(a[y],st[y],-1); swap(a[x],a[y]); change(a[x],st[x],1); change(a[y],st[y],1); } printf("%d\n",sum); } return 0; }
pain and happy in the cruel world.