BZOJ 2141: 排队
正文索引 [隐藏]
Description
排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量。幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。
Input
第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi¬,表示交换位置ai与位置bi的小朋友。
Output
输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。
Sample Input
【样例输入】
3
130 150 140
2
2 3
1 3
3
130 150 140
2
2 3
1 3
Sample Output
1
3
【样例说明】
未进行任何操作时,(2,3)满足条件;
操作1结束后,序列为130 140 150,不存在满足i<j且hi>hj的(i,j)对;
操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
【数据规模和约定】
对于100%的数据,1≤m≤2*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。
3
【样例说明】
未进行任何操作时,(2,3)满足条件;
操作1结束后,序列为130 140 150,不存在满足i<j且hi>hj的(i,j)对;
操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
【数据规模和约定】
对于100%的数据,1≤m≤2*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。
题解
离散化身高,我们建一棵树状数组套线段树。首先求得开始状态的逆序对,然后每次处理交换只需要知道两个交换元素之间的区间的大小信息就可以维护了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
#include<cstdio> #include<map> #include<algorithm> using namespace std; const int Maxn=20010; int n,m; int hi[Maxn]; int toHash[Maxn]; map<int,int> Hash; int tot; int Root[Maxn]; struct Btree{ int lx,rx; int sum; }; Btree tree[Maxn*510]; int nume; void modify(int &x,int left,int right,int pos,int delta){ if (!x){ x=++nume; tree[x].lx=tree[x].rx=0; tree[x].sum=0; } tree[x].sum+=delta; if (left==right){ }else{ int mid=(left+right)/2; if (pos<=mid) modify(tree[x].lx,left,mid,pos,delta); if (mid+1<=pos) modify(tree[x].rx,mid+1,right,pos,delta); } } int query(int x,int left,int right,int l,int r){ if (!x) return 0; if (l<=left && right<=r){ return tree[x].sum; }else{ int mid=(left+right)/2; int ret=0; if (l<=mid) ret+=query(tree[x].lx,left,mid,l,r); if (mid+1<=r) ret+=query(tree[x].rx,mid+1,right,l,r); return ret; } } inline int lowbit(int x){ return x&(-x); } inline void modifyTree(int pos,int val,int delta){ for (int i=val;i<=Maxn;i+=lowbit(i)) modify(Root[i],1,n,pos,delta); } inline int queryTree(int val,int left,int right){ if (left>right) return 0; int ret=0; for (int i=val;i;i-=lowbit(i)) ret+=query(Root[i],1,n,left,right); return ret; } int Ans=0; int x,y; int main(){ //freopen("2141.in","r",stdin); //freopen("2141.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&hi[i]); for (int i=1;i<=n;i++) toHash[i]=hi[i]; sort(toHash+1,toHash+n+1); for (int i=1;i<=n;i++) if (i==1 || toHash[i-1]!=toHash[i]){ Hash[toHash[i]]=++tot; } for (int i=1;i<=n;i++) hi[i]=Hash[hi[i]]; for (int i=n;i>=1;i--){ Ans+=queryTree(hi[i]-1,1,n); modifyTree(i,hi[i],1); } printf("%d\n",Ans); scanf("%d",&m); for (int i=1;i<=m;i++){ scanf("%d%d",&x,&y); if (x>y) swap(x,y); int cnt=y-x-1; if (cnt>0){ Ans-=(cnt-queryTree(hi[y],x+1,y-1)); Ans+=queryTree(hi[y]-1,x+1,y-1); Ans-=queryTree(hi[x]-1,x+1,y-1); Ans+=(cnt-queryTree(hi[x],x+1,y-1)); } if (hi[x]<hi[y]) Ans++; if (hi[x]>hi[y]) Ans--; /* for (int j=1;j<=n;j++) printf("%d ",hi[j]); printf("\n"); printf("(%d,%d)\n",x,y); printf("Height[%d]=%d Low:%d High:%d\n",x,hi[x],queryTree(hi[x]-1,x+1,y-1),(cnt-queryTree(hi[x],x+1,y-1))); printf("Height[%d]=%d Low:%d High:%d\n",y,hi[y],queryTree(hi[y]-1,x+1,y-1),(cnt-queryTree(hi[y],x+1,y-1))); */ modifyTree(x,hi[x],-1); modifyTree(x,hi[y],1); modifyTree(y,hi[y],-1); modifyTree(y,hi[x],1); swap(hi[x],hi[y]); printf("%d\n",Ans); } return 0; } |

原文链接:BZOJ 2141: 排队
WNJXYKの博客 版权所有,转载请注明出处。
还没有任何评论,你来说两句吧!