您的位置:首页 > 其它

【bzoj2141】【排队】【树状数组套平衡树】

2016-06-17 19:47 411 查看

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

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*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。
题解:
和动态逆序对那个题基本一样.
代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define N 20010
using namespace std;
int root
,sz,ls[N*20],rs[N*20],n,m,x,y,t
,a
,h
,ans,temp;
struct treap{int v,w,sum,rd;}tr[N*20];
int find(int x){
int l=1,r=n;
while (l<=r){
int mid=(l+r)>>1;
if (x<h[mid]) r=mid-1;
else if (x>h[mid]) l=mid+1;
else return mid;
}
}
int lowbit(int x){return x&(-x);}
void ins(int x){for(int i=x;i<=n;i+=lowbit(i)) t[i]++;}
int que(int x){
int ans(0);
for (int i=x;i;i-=lowbit(i)) ans+=t[i];
return ans;
}
void update(int k){
tr[k].sum=tr[ls[k]].sum+tr[rs[k]].sum+tr[k].w;
}
void lturn(int &k){
int t=rs[k];rs[k]=ls[rs[k]];ls[t]=k;
update(k);update(t);k=t;
}
void rturn(int &k){
int t=ls[k];ls[k]=rs[ls[k]];rs[t]=k;
update(k);update(t);k=t;
}
void insert(int &k,int v){
if (!k){k=++sz;tr[k].w=tr[k].sum=1;tr[k].v=v;tr[k].rd=rand();return;}
if (tr[k].v==v) tr[k].w++;
else if (v<tr[k].v){insert(ls[k],v);if (tr[ls[k]].rd<tr[k].rd) rturn(k);}
else{insert(rs[k],v);if (tr[rs[k]].rd<tr[k].rd) lturn(k);}
update(k);
}
void del(int &k,int v){
if (!k) return;
if (tr[k].v==v){
if (tr[k].w>1) tr[k].w--;
else{
if (ls[k]*rs[k]==0) k=ls[k]+rs[k];
else if (tr[ls[k]].rd<tr[k].rd) {rturn(k);del(k,v);}
else{lturn(k);del(k,v);}
}
}
else if (v<tr[k].v) del(ls[k],v);
else del(rs[k],v);
update(k);
}
void getmn(int k,int v){
if (!k) return;
if (tr[k].v==v) temp+=tr[ls[k]].sum;
else if (v<tr[k].v) getmn(ls[k],v);
else {temp+=tr[ls[k]].sum+tr[k].w;getmn(rs[k],v);}
}
void getmx(int k,int v){
if (!k) return;
if (tr[k].v==v){temp+=tr[rs[k]].sum;}
else if (v>tr[k].v) getmx(rs[k],v);
else{temp+=tr[rs[k]].sum+tr[k].w;getmx(ls[k],v);}
}
int quemn(int x,int v){
temp=0;
for (int i=x;i;i-=lowbit(i)) getmn(root[i],v);
return temp;
}
int quemx(int x,int v){
temp=0;
for (int i=x;i;i-=lowbit(i)) getmx(root[i],v);
return temp;
}
void add(int x,int v){for (int i=x;i<=n;i+=lowbit(i)) insert(root[i],v);}
void qdel(int x,int v){for (int i=x;i<=n;i+=lowbit(i)) del(root[i],v);}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]),h[i]=a[i];
sort(h+1,h+n+1);
for (int i=1;i<=n;i++) a[i]=find(a[i]);
for (int i=n;i>=1;i--){
ins(a[i]);ans+=que(a[i]-1);
}
printf("%d\n",ans);
for (int i=1;i<=n;i++) add(i,a[i]);
scanf("%d",&m);
for (int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
if (x>y) swap(x,y);if (a[x]==a[y]) {printf("%d\n",ans);continue;}
if (x+1==y){
if (a[x]<a[y]) ans++;else ans--;
qdel(x,a[x]);add(x,a[y]);qdel(y,a[y]);add(y,a[x]);
swap(a[x],a[y]);printf("%d\n",ans);continue;
}
int r=y-1;
ans-=quemn(r,a[x])-quemn(x,a[x]);
ans+=quemx(r,a[x])-quemx(x,a[x]);
ans-=quemx(r,a[y])-quemx(x,a[y]);
ans+=quemn(r,a[y])-quemn(x,a[y]);
if (a[x]<a[y]) ans++;else ans--;
qdel(x,a[x]);add(x,a[y]);
qdel(y,a[y]);add(y,a[x]);
swap(a[x],a[y]);printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: