对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
标签:owb std 排列 using 序列 sum note -- 顺序
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define maxn 100011 struct note{ int x,y,t; int flag; }a[maxn],b[maxn]; int n,m,c[maxn],pos[maxn],ans[maxn]; #define lowbit(x) x&-x inline bool cmpx(note q,note qq) { if(q.x==qq.x){return q.y<qq.y;} return q.x<qq.x; } inline bool cmpt(note q,note qq){ return q.t<qq.t; } void add(int u,int v){for(int j=u;j<=n;c[j]+=v,j+=lowbit(j));} int query(int u){int sum=0;for(int j=u;j;sum+=c[j],j-=lowbit(j));return sum;} void CDQ(int l,int r) { if(l>=r)return; int mid=(l+r)>>1,size=r-l+1,cnt=0; for(int i=l;i<=mid;i++)b[++cnt]=a[i],b[cnt].flag=0;for(int i=mid+1;i<=r;i++) b[++cnt]=a[i],b[cnt].flag=1; sort(b+1,b+1+cnt,cmpx); for(int i=1;i<=size;i++) if(!b[i].flag) add(b[i].y,1); else ans[b[i].t]+=query(n)-query(b[i].y); for(int i=1;i<=size;i++) if(!b[i].flag)add(b[i].y,-1); for(int i=size;i>=1;i--) if(!b[i].flag)add(b[i].y,1);else ans[b[i].t]+=query(b[i].y); for(int i=size;i>=1;i--) if(!b[i].flag)add(b[i].y,-1); CDQ(l,mid);if(mid<r) CDQ(mid+1,r); } void debug() { for(int i=1;i<=n;i++) cout<<a[i].x<<‘ ‘<<a[i].y<<‘ ‘<<a[i].t<<endl; } int main() { scanf("%d %d",&n,&m); int Timerec=n; for(int i=1;i<=n;i++){int x;scanf("%d",&x);a[i].x=i,a[i].y=x;pos[x]=i;} for(int i=1;i<=m;i++){int x;scanf("%d",&x);a[pos[x]].t=Timerec--;} //debug(); for(int i=1;i<=n;i++)if(!a[i].t){a[i].t=Timerec--;} sort(a+1,a+1+n,cmpt);CDQ(1,n); long long Ans=0; for(int i=1;i<=n;i++) Ans+=ans[i]; for(int i=n;i>n-m;i--) { printf("%lld\n",Ans); Ans-=ans[i]; } }
http://www.hekai.site/wordpress/2017/08/26/cdq%E5%88%86%E6%B2%BB%E8%AF%A6%E8%A7%A3%EF%BC%88bzoj3262-%E9%99%8C%E4%B8%8A%E8%8A%B1%E5%BC%80%EF%BC%89/
HKdalao的题解,题目不一样,但思路差不多吧
标签:owb std 排列 using 序列 sum note -- 顺序
原文地址:http://www.cnblogs.com/dancer16/p/7455797.html