您的位置:首页 > 其它

[bzoj2141]排队

2016-01-15 14:38 363 查看
  树套树。。我写了线段树套treap= =外层线段树表示各段区间,每段区间内按权值大小开个treap

  设数列为map[],一开始求出逆序对个数。

  每次假设交换l和r这两位置的数,答案就要减去[l+r,r-1]中比map[l]小的数的个数,再减去[l+1,r-1]中比map[r]大的数的个数,

                     加上[l+1,r-1]中比map[l]大的数的个数,再加上[l+1,r-1]中比map[r]小的数的个数。。最后看下map[l]和map[r]的大小关系

  挺显然的。。交换的时候就在l和r位置所在的线段树节点里面改(删掉原来的,插入交换后的数)

  一开始外层的zkw线段树写挂了= =

  感觉树套树空间问题各种蛋疼。。。每次都要算个半天= =

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=26233;
int l[maxn*20],r[maxn*20],sz[maxn*20],w[maxn*20],num[maxn*20],rnd[maxn*20],tot;
int rt[66233],size;
int mp[maxn];
int i,j,n,m,ans,L,R;

int ra;char rx;
inline int read(){
rx=getchar(),ra=0;
while(rx<'0'||rx>'9')rx=getchar();
while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
}

inline void upd(int x){sz[x]=sz[l[x]]+w[x]+sz[r[x]];}
inline void lturn(int &x,int R){
r[x]=l[R],l[R]=x,sz[R]=sz[x],upd(x),x=R;
}
inline void rturn(int &x,int L){
l[x]=r[L],r[L]=x,sz[L]=sz[x],upd(x),x=L;
}
void ins(int &x,int v){
if(!x){x=++tot,rnd[x]=rand(),sz[x]=w[x]=1,num[x]=v;return;}
sz[x]++;
if(v==num[x])w[x]++;else
if(v<num[x]){
ins(l[x],v);
if(rnd[l[x]]<rnd[x])rturn(x,l[x]);
}else{
ins(r[x],v);
if(rnd[r[x]]<rnd[x])lturn(x,r[x]);
}
}
void del(int &x,int v){
if(num[x]==v){
if(w[x]>1)w[x]--,sz[x]--;else
if(!(l[x]&&r[x]))x=l[x]|r[x];else
if(rnd[l[x]]<rnd[r[x]])rturn(x,l[x]),del(x,v);
else lturn(x,r[x]),del(x,v);
}else if(v<num[x])sz[x]--,del(l[x],v);
else sz[x]--,del(r[x],v);
}
int smnum(int x,int v){
if(!x)return 0;
if(v<num[x])return smnum(l[x],v);
else if(v==num[x])return sz[l[x]]+smnum(r[x],v);
else return sz[l[x]]+w[x]+smnum(r[x],v);
}
int binum(int x,int v){
if(!x)return 0;
if(v>num[x])return binum(r[x],v);
else if(v==num[x])return sz[r[x]]+binum(l[x],v);
else return sz[r[x]]+w[x]+binum(l[x],v);
}

int query(int l,int r,int v,bool big){
if(l>r)return 0;
l+=size,r+=size;
if(l==r)return big?binum(rt[l],v):smnum(rt[l],v);

int sum=big?(binum(rt[l],v)+binum(rt[r],v)):(smnum(rt[l],v)+smnum(rt[r],v));
for(;l^r^1;l>>=1,r>>=1){
if(!(l&1))sum+=big?binum(rt[l^1],v):smnum(rt[l^1],v);
if(r&1)sum+=big?binum(rt[r^1],v):smnum(rt[r^1],v);
}
return sum;
}

int main(){
n=read();
for(size=1;size<n;size<<=1);size--;
for(i=1;i<=n;i++){
mp[i]=read();
for(j=i+size;j>1;j>>=1)if(j&1)ans+=binum(rt[j^1],mp[i]);
for(j=i+size;j;j>>=1)ins(rt[j],mp[i]);
}
printf("%d\n",ans);
m=read();
while(m--){
L=read(),R=read();if(L>R)swap(L,R);
if(L==R){printf("%d\n",ans);continue;}
ans-=query(L+1,R-1,mp[L],0)+query(L+1,R-1,mp[R],1);
ans+=query(L+1,R-1,mp[L],1)+query(L+1,R-1,mp[R],0);
if(mp[L]<mp[R])ans++;else if(mp[L]>mp[R])ans--;
for(j=L+size;j;j>>=1)del(rt[j],mp[L]);
for(j=R+size;j;j>>=1)del(rt[j],mp[R]);
for(j=R+size;j;j>>=1)ins(rt[j],mp[L]);
for(j=L+size;j;j>>=1)ins(rt[j],mp[R]);
swap(mp[L],mp[R]);
printf("%d\n",ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: