BZOJ 2141排队(树状数组套Treap)
2015-04-14 19:53
225 查看
2141: 排队
Time Limit: 4 Sec Memory Limit: 259 MBSubmit: 798 Solved: 323
[Submit][Status][Discuss]
Description
排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足hi>hj且i<j的(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
Sample Output
10
3
【样例说明】
未进行任何操作时,(2,3)满足条件;
操作1结束后,序列为130 140 150,不存在满足ihj的(i,j)对;
操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
【数据规模和约定】
对于100%的数据,1≤m≤2*10^3,1≤n≤2*10^4,1≤hi≤10^9,ai≠bi,1≤ai,bi≤n。
代码写的不是很美,不过需要注意的是找到的节点必须是严格大于或者小于
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; #define lowbit(x) (x&-x) #define N 20100 int n,m,ans,num ; struct Node{ Node *ch[2]; int rank,value,siz; Node() {ch[0]=ch[1]=NULL;} Node(int v,int r) { ch[0] = ch[1] = NULL; value = v; rank = r; siz = 1; } void push_up() { siz = 1; if(ch[0]!=NULL) siz += ch[0]->siz; if(ch[1]!=NULL) siz += ch[1]->siz; } }*root ; //单旋转操作 void rotate(Node *(&node),int d) { Node *tem = node->ch[d^1]; node->ch[d^1] = tem->ch[d]; node->push_up(); tem->ch[d] = node; tem->push_up(); node = tem; } //插入一个新节点 void insert(Node *(&node),int v) { if(node==NULL){ node = new Node(v,rand()); return; } int d = (node->value <= v); insert(node->ch[d],v); node->push_up(); if(node->ch[d]->rank > node->rank) rotate(node,d^1); } //查找小于v的数量tag==0不严格 int quary(Node *(&node),int v,int tag) { if(node == NULL) return 0; int size = (node->ch[0]==NULL?0:node->ch[0]->siz); if(tag==0){ if(node->value <= v) return size+1+quary(node->ch[1],v,tag); else return quary(node->ch[0],v,tag); } else{ if(node->value < v) return size+1+quary(node->ch[1],v,tag); else return quary(node->ch[0],v,tag); } } //移除node节点 void remove(Node *(&node)){ if(node->ch[0]==NULL){node = node->ch[1];return;} if(node->ch[1]==NULL){node = node->ch[0];return;} int rank1 = node->ch[0]->rank; int rank2 = node->ch[1]->rank; int d = (rank1>rank2)?1:0; rotate(node,d); remove(node->ch[d]); node -> push_up(); } //移除节点权值为v的节点 void modify(Node *(&node),int v){ if(node==NULL) return; if(node->value == v){ remove(node); return; } int d = (node->value < v); modify(node->ch[d],v); node->push_up(); } void add(int id,int v){ for(int i = id;i<=n;i+=lowbit(i)) insert(root[i],v); } //得到id位置之前比y值小的数个数 int getSum(int id,int y,int tag){ int sum = 0; for(int i = id;i>=1;i-=lowbit(i)) sum += quary(root[i],y,tag); return sum; } void change(int id,int v1,int v2){ for(int i = id;i<=n;i+=lowbit(i)){ modify(root[i],v1); insert(root[i],v2); } } void delet(Node *(&node)){ if(node == NULL) return; delet(node->ch[0]); delet(node->ch[1]); delete node; node = NULL; } void init(){ ans = 0; for(int i = 0;i<=n;i++){ delet(root[i]); root[i] = NULL; } } int main(){ int x,y; //freopen("Test.txt","r",stdin); while(~scanf("%d",&n)){ init(); for(int i = 1;i<=n;i++){ scanf("%d",&num[i]); add(i,num[i]); } for(int i = 1;i<=n;i++){ ans += (i-1 - getSum(i-1,num[i],0)); } 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 dox = getSum(y-1,num[x],1) - getSum(x,num[x],1); int upx = y-1-x-getSum(y-1,num[x],0) + getSum(x,num[x],0); int doy = getSum(y-1,num[y],1) - getSum(x,num[y],1); int upy = y-1-x-getSum(y-1,num[y],0) + getSum(x,num[y],0); ans -= (dox+upy); ans += (doy+upx); if(num[x]>num[y]) ans -= 1; if(num[x]<num[y]) ans += 1; printf("%d\n",ans); change(x,num[x],num[y]); change(y,num[y],num[x]); swap(num[x],num[y]); } } return 0; }
相关文章推荐
- BZOJ - 2141 排队(树状数组套treap||分块)
- BZOJ 2141 排队(树状数组套treap)
- BZOJ 2141 排队 分块+树状数组
- BZOJ 2141 排队 [分块+树状数组]
- [BZOJ]2141: 排队 分块+树状数组
- [BZOJ] 2141 - Atlantis - 排队 - 树状数组求逆序对 - 分块求区间比 k 小
- BZOJ 2141 排队 分块+树状数组,详细题解
- Bzoj 2141: 排队 分块,逆序对,树状数组
- [BZOJ2141]排队(分块+树状数组求逆序对)
- 【bzoj2141】排队 分块+树状数组
- bzoj 2141: 排队 (树状数组套线段树)
- BZOJ 3295 [Cqoi2011]动态逆序对 - 树状数组套主席树/树状数组套treap
- bzoj2141【分块+树状数组】
- [树状数组 线段树] BZOJ 3333 排队计划
- 2141: 排队 分块+树状数组
- BZOJ 3333: 排队计划 树状数组 线段树
- 【BZOJ 2141】排队【分块+Treap】
- bzoj2141 分块套树状数组/树套树
- bzoj 2141: 排队 树状数组套线段树
- [SDOI2009][BZOJ1878][前缀和][树状数组]HH的项链