对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删
除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数
标签:事先 逆序对数 针对 play std efi 计算 zoj output
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long 5 #define maxn 100005 6 #define maxm 50005 7 using namespace std; 8 int n,m; 9 int c[maxn],a[maxn],s[maxn],e[maxm],pos[maxn],t[maxm]; 10 ll ans; 11 void add(int x,int z){while(x<=n){c[x]+=z;x+=x&(-x);}} 12 int sum(int x){int ans=0;while(x){ans+=c[x];x-=x&(-x);}return ans;} 13 int query(int l,int r){if(l>r)return 0;return sum(r)-sum(l-1);} 14 bool cmp(int x,int y){return pos[x]<pos[y];} 15 void solve(int l,int r){ 16 if(l==r)return; 17 int mid=(l+r)/2; 18 solve(l,mid);solve(mid+1,r); 19 int tx=l,ty=mid+1; 20 while(tx<=mid||ty<=r){ 21 if(ty>r||(tx<=mid&&pos[e[tx]]<pos[e[ty]]))add(e[tx++],1); 22 else{s[e[ty]]-=query(e[ty],n);ty++;} 23 } 24 for(int i=l;i<=mid;i++)add(e[i],-1); 25 tx=mid,ty=r; 26 while(tx>=l||ty>=mid+1){ 27 if((ty<mid+1)||(tx>=l&&pos[e[tx]]>pos[e[ty]]))add(e[tx--],1); 28 else{s[e[ty]]-=query(1,e[ty]);ty--;} 29 } 30 for(int i=l;i<=mid;i++)add(e[i],-1); 31 sort(e+l,e+r+1,cmp); 32 } 33 int main(){ 34 scanf("%d%d",&n,&m); 35 for(int i=1;i<=n;i++)scanf("%d",&a[i]),pos[a[i]]=i; 36 for(int i=1;i<=n;i++){s[a[i]]+=query(a[i]+1,n);add(a[i],1);ans+=s[a[i]];} 37 memset(c,0,sizeof(c)); 38 for(int i=n;i>=1;i--){s[a[i]]+=sum(a[i]);add(a[i],1);} 39 memset(c,0,sizeof(c)); 40 for(int i=1;i<=m;i++)scanf("%d",&e[i]),t[i]=e[i]; 41 solve(1,m); 42 for(int i=1;i<=m;i++){ 43 printf("%lld\n",ans); 44 ans-=s[t[i]]; 45 } 46 return 0; 47 }
话说这是不是有点压行啊。。。
标签:事先 逆序对数 针对 play std efi 计算 zoj output
原文地址:https://www.cnblogs.com/2017SSY/p/10199519.html