您的位置:首页 > 其它

BZOJ 2141排队(树状数组套Treap)

2015-04-14 19:53 225 查看

2141: 排队

Time Limit: 4 Sec Memory Limit: 259 MB

Submit: 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

1

0

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: