题解:
将交换看作两个插入+两个删除。
然后CDQ。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 30050 #define ll long long inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,m,cnt,stu[N]; struct Pair { int x,id; }tk[N]; bool cmp(Pair a,Pair b) { return a.x<b.x; } struct node { int pos,val,id,wgt; node(){} node(int p,int v,int i,int w):pos(p),val(v),id(i),wgt(w){} }p[N],tmp[N]; void Sort(int l,int r) { int mid = (l+r)>>1; int i=l,j=mid+1,k=l; while(i<=mid&&j<=r) { while(i<=mid&&p[i].pos<=p[j].pos) { tmp[k]=p[i]; i++,k++; } while(j<=r&&p[i].pos>p[j].pos) { tmp[k]=p[j]; j++,k++; } } while(i<=mid) { tmp[k]=p[i]; i++,k++; } while(j<=r) { tmp[k]=p[j]; j++,k++; } for(i=l;i<=r;i++) p[i]=tmp[i]; } int f[N]; void up(int x,int d) { if(!x)return ; while(x<N)f[x]+=d,x+=(x&-x); } int down(int x) { if(!x)return 0; int ret = 0; while(x)ret+=f[x],x-=(x&-x); return ret; } int k = 0; ll ans[N]; void cdq(int l,int r) { if(l==r)return ; int mid = (l+r)>>1; cdq(l,mid),cdq(mid+1,r); Sort(l,mid),Sort(mid+1,r); int i,j; j=l; for(i=mid+1;i<=r;i++) { while(j<=mid&&p[j].pos<=p[i].pos)up(p[j].val,p[j].wgt),j++; ans[p[i].id]+=p[i].wgt*(down(k)-down(p[i].val)); } for(j=j-1;j>=l;j--)up(p[j].val,-p[j].wgt); j=mid; for(i=r;i>mid;i--) { while(j>=l&&p[j].pos>=p[i].pos)up(p[j].val,p[j].wgt),j--; ans[p[i].id]+=p[i].wgt*down(p[i].val-1); } for(j=j+1;j<=mid;j++)up(p[j].val,-p[j].wgt); } int main() { n=rd(); for(int x,i=1;i<=n;i++) { x=rd(); tk[i].x=x,tk[i].id=i; } sort(tk+1,tk+n+1,cmp); for(int las=-1,i=1;i<=n;i++) { if(las!=tk[i].x) { las=tk[i].x; k++; } int j = tk[i].id; p[j]=node(j,k,0,1); stu[j] = k; } m=rd(); for(int l,r,i=1;i<=m;i++) { l=rd(),r=rd(); p[++n]=node(l,stu[l],i,-1); p[++n]=node(r,stu[r],i,-1); swap(stu[l],stu[r]); p[++n]=node(l,stu[l],i,1); p[++n]=node(r,stu[r],i,1); } cdq(1,n); for(int i=1;i<=m;i++)ans[i]+=ans[i-1]; for(int i=0;i<=m;i++)printf("%lld ",ans[i]); return 0; }