BZOJ3295: [Cqoi2011]动态逆序对
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3295
CDQ分治加凸包,水题一道,看看程序就懂了。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define inf 1<<30 6 #define maxn 100005 7 #define maxm 50005 8 using namespace std; 9 int n,m,t[maxn],a[maxn],b[maxn],f[maxn],ans[maxm]; 10 long long sum; 11 struct fuck{int id,x,y;}p[maxm],q[maxm]; 12 int read(){ 13 int x=0,f=1; char ch; 14 for(ch=getchar();ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1; 15 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 16 return x*f; 17 } 18 bool cmp(fuck a,fuck b){return a.x<b.x;} 19 void change(int x,int y){for(int i=x;i<=n;i+=i&-i) t[i]+=y;} 20 int query(int x){int y=0; for(int i=x;i;i-=i&-i) y+=t[i]; return y;} 21 void solve(int l,int r){ 22 if(l==r) return; 23 int mid=(l+r)>>1; 24 solve(l,mid); solve(mid+1,r); 25 sort(q+l,q+mid+1,cmp); sort(q+mid+1,q+r+1,cmp); 26 int i=l,j=mid+1,last=0; 27 while(j<=r){ 28 while(i<=mid&&q[i].x<q[j].x) change(q[i].y,1),last=i++; 29 ans[q[j].id]-=query(q[j].y); 30 j++; 31 } 32 for(int i=l;i<=last;i++) change(q[i].y,-1); 33 } 34 int main(){ 35 n=read(); m=read(); 36 for(int i=1;i<=n;i++) a[i]=read(),b[a[i]]=i; 37 for(int i=1;i<=m;i++){p[i].y=read(); p[i].x=b[p[i].y]; p[i].id=i;} 38 for(int i=1;i<=n;i++){f[i]+=i-1-query(a[i]); sum+=f[i]; change(a[i],1);} 39 memset(t,0,sizeof(t)); 40 for(int i=n;i;i--){f[i]+=query(a[i]); change(a[i],1);} 41 memset(t,0,sizeof(t)); 42 for(int i=1;i<=m;i++) ans[i]=f[p[i].x]; 43 for(int i=1;i<=m;i++) q[i].id=p[i].id,q[i].x=n+1-p[i].x,q[i].y=p[i].y; solve(1,m); 44 for(int i=1;i<=m;i++) q[i].id=p[i].id,q[i].x=p[i].x,q[i].y=n+1-p[i].y; solve(1,m); 45 for(int i=1;i<=m;i++){printf("%lld\n",sum); sum-=ans[i];} 46 return 0; 47 }