[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线段树写挂了= =
感觉树套树空间问题各种蛋疼。。。每次都要算个半天= =
View Code
设数列为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
相关文章推荐
- CentOS 6.2图形界面允许root用户登录
- Linux磁盘分区
- oracle入门
- 基于nginx tomcat redis分布式web应用的session共享配置
- oracle入门
- gRPC异步处理应答
- C++编译期多态与运行期多态
- gRPC异步处理应答
- 平时关注网站汇总
- 动态设置Android状态栏颜色
- oracle运用(四) oracle数据库NUMBER类型详解
- 【Western Digital】三角板自校准标准流程
- ListView - 基本使用方法&适配器封装(参考鸿神)
- 微软CIO如何与业务部门打交道?
- php socket通信(tcp/udp)
- 更改虚拟内存文件存放位置释放系统盘可用空间
- 全本一六年一月再论人工智能
- js播放wav格式的录音文件
- 剖析C++中的常量表达式与省略号的相关作用
- 【bcb 6.0】http相关的控件