bzoj 2141: 排队 树状数组套线段树
2016-10-22 11:56
309 查看
题目
传送门分析
树状数组套线段树。对于每一次交换x和y的操作,先减去在交换之前x和y分别与a[x+1..y-1]产生了多少逆序对,再加上交换后x和y分别与a[x+1..y-1]产生了多少逆序对,然后再进行交换操作就好了。
一开始的想法是线段树套线段树,但是很明显线段树各方面的指标都没有树状数组优秀,所以就果断改成了树状数组。
貌似分块+二分或分块套树状数组或线段树套平衡树也是可做的,懒得打了。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define N 20005 using namespace std; int a ,root ,n,m,tot; struct Segtree{int l,r,size;}t[10000005]; int lowbit(int x) { return x&(-x); } void Segtree_ins(int &d,int l,int r,int x,int y) { if (!d) d=++tot; t[d].size+=y; if (l==r) return; int mid=(l+r)/2; if (x<=mid) Segtree_ins(t[d].l,l,mid,x,y); else Segtree_ins(t[d].r,mid+1,r,x,y); } int Segtree_bigger(int &d,int l,int r,int x) { if (l==r||!d) return 0; int mid=(l+r)/2; if (x<=mid) return t[t[d].r].size+Segtree_bigger(t[d].l,l,mid,x); else return Segtree_bigger(t[d].r,mid+1,r,x); } int Segtree_smaller(int &d,int l,int r,int x) { if (l==r||!d) return 0; int mid=(l+r)/2; if (x<=mid) return Segtree_smaller(t[d].l,l,mid,x); else return t[t[d].l].size+Segtree_smaller(t[d].r,mid+1,r,x); } void Treearr_ins(int x,int y) { while (x<=n) { Segtree_ins(root[x],1,1000000000,y,1); x+=lowbit(x); } } void Treearr_del(int x,int y) { while (x<=n) { Segtree_ins(root[x],1,1000000000,y,-1); x+=lowbit(x); } } int Treearr_bigger(int x,int y) { int ans=0; while (x) { ans+=Segtree_bigger(root[x],1,1000000000,y); x-=lowbit(x); } return ans; } int Treearr_smaller(int x,int y) { int ans=0; while (x) { ans+=Segtree_smaller(root[x],1,1000000000,y); x-=lowbit(x); } return ans; } int main() { scanf("%d",&n); int ans=0; for (int i=1;i<=n;i++) { scanf("%d",&a[i]); ans+=Treearr_bigger(i-1,a[i]); Treearr_ins(i,a[i]); } printf("%d\n",ans); scanf("%d",&m); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); if (x>y) swap(x,y); ans-=Treearr_smaller(y-1,a[x])-Treearr_smaller(x,a[x])+Treearr_bigger(y-1,a[y])-Treearr_bigger(x,a[y]); ans+=Treearr_bigger(y-1,a[x])-Treearr_bigger(x,a[x])+Treearr_smaller(y-1,a[y])-Treearr_smaller(x,a[y]); if (a[x]<a[y]) ans++; else if (a[x]>a[y]) ans--; printf("%d\n",ans); Treearr_del(x,a[x]);Treearr_del(y,a[y]); swap(a[x],a[y]); Treearr_ins(x,a[x]);Treearr_ins(y,a[y]); } return 0; }
相关文章推荐
- BZOJ_2141_排队_树状数组+分块
- BZOJ 2141 排队 线段树套替罪羊
- bzoj2141: 排队(分块+树状数组)
- 【BZOJ2141】排队 树状数组+分块
- 【bzoj2141】 排队 树状数组+主席树
- 【bzoj2141】排队 [国家集训队2011]排队(魏铭) 树套树 线段树套替罪羊树
- BZOJ 3333 排队计划 树状数组+线段树
- bzoj 2141: 排队 (树状数组套线段树)
- 【bzoj2141】排队
- BZOJ 3744 Gty的妹子序列 分块+树状数组+可持久化线段树
- BZOJ 2141: 排队 CDQ分治+bit
- BZOJ 2141 排队 分块
- 【bzoj2141】【排队】【树状数组套平衡树】
- BZOJ 2141 排队 [分块+树状数组]
- [BZOJ2674]Attack(整体二分+树状数组套线段树)
- 【bzoj2141】排队 分块+树状数组
- 【国家集训队2011】【BZOJ2141】排队
- 【BZOJ2141】排队(树套树)
- bzoj 2141: 排队
- [整体二分 树状数组套线段树] BZOJ 2674 Attack