bzoj 2141 线段树套权值线段树
2016-10-19 14:37
351 查看
首先交换的两个数两边的数产生的逆序对数不变。
那么只需要考虑中间的数和两个数本身。
只考虑第一个数大于第二个数的情况(小于的情况是这个的逆过程)
首先答案-1(这两个数产生的逆序对)
答案-位置在两个数之间并且值也在两个数之间的数的个数×2
答案-位置在两个数之间并且值与两个数中的一个相等的数的个数
可以用树套树维护这个东西。
那么只需要考虑中间的数和两个数本身。
只考虑第一个数大于第二个数的情况(小于的情况是这个的逆过程)
首先答案-1(这两个数产生的逆序对)
答案-位置在两个数之间并且值也在两个数之间的数的个数×2
答案-位置在两个数之间并且值与两个数中的一个相等的数的个数
可以用树套树维护这个东西。
#include <bits/stdc++.h> using namespace std; #define N 21000 #define M 11000000 #define A 1000000010 #define ll long long int n,m,cnt,l1,r1,l2,r2; int a ; int ch[M][2],val[M],root[N<<2]; ll ans; struct val_tree { void insert(int l,int r,int &x,int y,int v) { if(!x)x=++cnt; val[x]+=v; if(l==r)return; int mid=(l+r)>>1; if(mid>=y)insert(l,mid,ch[x][0],y,v); else insert(mid+1,r,ch[x][1],y,v); } int query(int l,int r,int x) { if(l2<=l&&r<=r2) return val[x]; int mid=(l+r)>>1,ret=0; if(mid>=l2)ret+=query(l,mid,ch[x][0]); if(mid<r2) ret+=query(mid+1,r,ch[x][1]); return ret; } }tr2; struct pos_tree { void insert(int l,int r,int now,int x,int y,int v) { tr2.insert(1,A,root[now],y,v); if(l==r)return; int mid=(l+r)>>1; if(mid>=x)insert(l,mid,now<<1,x,y,v); else insert(mid+1,r,now<<1|1,x,y,v); } int query(int l,int r,int now) { if(l1<=l&&r<=r1) return tr2.query(1,A,root[now]); int mid=(l+r)>>1,ret=0; if(mid>=l1)ret+=query(l,mid,now<<1); if(mid<r1) ret+=query(mid+1,r,now<<1|1); return ret; } }tr1; int main() { //freopen("tt.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); l1=1;r1=n;l2=a[i]+1;r2=A; ans+=tr1.query(1,n,1); tr1.insert(1,n,1,i,a[i],1); } printf("%lld\n",ans); scanf("%d",&m); for(int x,y;m--;) { scanf("%d%d",&x,&y); if(x>y)swap(x,y); if(a[x]==a[y]){printf("%lld\n",ans);continue;} l1=x+1;r1=y-1; if(a[x]>a[y]) { l2=a[y]+1;r2=a[x]-1;ans--; if(r1>=l1&&r2>=l2)ans-=tr1.query(1,n,1)*2; l2=a[y];r2=a[y]; if(r1>=l1)ans-=tr1.query(1,n,1); l2=a[x];r2=a[x]; if(r1>=l1)ans-=tr1.query(1,n,1); } else { l2=a[x]+1;r2=a[y]-1;ans++; if(r1>=l1&&r2>=l2)ans+=tr1.query(1,n,1)*2; l2=a[x];r2=a[x]; if(r1>=l1)ans+=tr1.query(1,n,1); l2=a[y];r2=a[y]; if(r1>=l1)ans+=tr1.query(1,n,1); } tr1.insert(1,n,1,x,a[x],-1); tr1.insert(1,n,1,y,a[y],-1); swap(a[x],a[y]); tr1.insert(1,n,1,x,a[x],1); tr1.insert(1,n,1,y,a[y],1); printf("%lld\n",ans); } return 0; }
相关文章推荐
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
- 【BZOJ3110】【Zjoi2013】K大数查询 树套树 权值线段树套区间线段树
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
- 【bzoj3110】【ZJOI2013】【K大数查询】【权值线段树套位置线段树】
- 【BZOJ3110】【codevs1616】K大数查询,权值线段树套普通线段树
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
- bzoj 2120&&2453 线段树套权值线段树
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
- [树状数组套权值线段树] BZOJ 1901 Zju2112 Dynamic Rankings
- bzoj 2141: 排队 (树状数组套线段树)
- BZOJ_3685_普通van Emde Boas树_权值线段树
- 【bzoj3702】二叉树 权值线段树
- [BZOJ1503]郁闷的出纳员 动态开点权值线段树模板
- bzoj 4627: [BeiJing2016]回转寿司 -- 权值线段树
- [主席树 树状数组套权值线段树] BZOJ 1146 [CTSC2008]网络管理Network
- bzoj3295 动态逆序对【树状数组套权值线段树】
- 【bzoj4719】[Noip2016]天天爱跑步 权值线段树合并
- 【bzoj2141】排队 [国家集训队2011]排队(魏铭) 树套树 线段树套替罪羊树
- 【bzoj 1112】砖块Klo(权值线段树)