bzoj2141 分块套树状数组/树套树
2017-10-26 16:55
267 查看
题意:动态维护逆序对,每次会交换两个数。
首先离散一波。
然后这题其实很显然,分块处理先,然后对于每次交换,只有在x,y之间的才有用。
那么在bl[x]+1和bl[y]-1之间的数都是整块,可以直接用bit维护。
否则就是一个块内的,就可以直接暴力维护了。
感觉我的实现姿势不好,写的很丑,看了po姐的感觉惭愧。。于是重新来一了几发。
树套树也可以做。以后回来填坑。
首先离散一波。
然后这题其实很显然,分块处理先,然后对于每次交换,只有在x,y之间的才有用。
那么在bl[x]+1和bl[y]-1之间的数都是整块,可以直接用bit维护。
否则就是一个块内的,就可以直接暴力维护了。
感觉我的实现姿势不好,写的很丑,看了po姐的感觉惭愧。。于是重新来一了几发。
树套树也可以做。以后回来填坑。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; const int N=1e5+5; int bl ,n,m; int cnt[200] ,pre ,a ,ans; struct node { int x,y; }b ; bool cmp(node a,node b) { return a.x<b.x; } inline int lowbit(int x) { return x&(-x); } inline void add(int t[],int x) { while (x<=n) { ++t[x]; x+=lowbit(x); } } inline void decrease(int t[],int x) { while (x<=n) { t[x]--; x+=lowbit(x); } } inline int get(int t[],int x) { int ans=0; while (x>0) { ans+=t[x]; x-=lowbit(x); } return ans; } int main() { scanf("%d",&n); fo(i,1,n) scanf("%d",&b[i].x),b[i].y=i; sort(b+1,b+1+n,cmp); int tot=0; fo(i,1,n) { if (b[i].x!=b[i-1].x)++tot; a[b[i].y]=tot; } fd(i,n,1) { ans+=get(pre,a[i]-1); add(pre,a[i]); } int c=sqrt(n); //int c=static_cast<int>(sqrt(n)+1e-7); fo(i,1,n)add(cnt[(i-1)/c],a[i]); printf("%d\n",ans); scanf("%d",&m); while (m--) { int x,y; scanf("%d%d",&x,&y); if (x>y)swap(x,y); int l=(x-1)/c,r=(y-1)/c; l++,r--; if (l<=r) { fo(i,l,r) { ans-=get(cnt[i],a[x]-1); ans+=get(cnt[i],n)-get(cnt[i],a[x]); ans+=get(cnt[i],a[y]-1); ans-=get(cnt[i],n)-get(cnt[i],a[y]); } fo(i,x+1,l*c) { if (a[i]<a[x])--ans; if (a[i]>a[x])++ans; if (a[i]<a[y])++ans; if (a[i]>a[y])--ans; } fo(i,(r+1)*c+1,y-1) { if (a[i]<a[x])--ans; if (a[i]>a[x])++ans; if (a[i]<a[y])++ans; if (a[i]>a[y])--ans; } } else { fo(i,x+1,y-1) { if (a[i]<a[x])--ans; if (a[i]>a[x])++ans; if (a[i]<a[y])++ans; if (a[i]>a[y])--ans; } } if (a[x]>a[y])ans--; else if (a[x]<a[y])ans++; decrease(cnt[(x-1)/c],a[x]); decrease(cnt[(y-1)/c],a[y]); swap(a[x],a[y]); add(cnt[(x-1)/c],a[x]); add(cnt[(y-1)/c],a[y]); printf("%d\n",ans); } }
相关文章推荐
- BZOJ 2141排队(树状数组套Treap)
- BZOJ 2141 排队 分块+树状数组
- bzoj 2141: 排队 (树状数组套线段树)
- 【bzoj2141】排队 分块+树状数组
- BZOJ 2141 排队(树状数组套treap)
- [BZOJ] 2141 - Atlantis - 排队 - 树状数组求逆序对 - 分块求区间比 k 小
- [BZOJ2141]排队(分块+树状数组求逆序对)
- BZOJ 2141 排队 分块+树状数组,详细题解
- Bzoj 2141: 排队 分块,逆序对,树状数组
- BZOJ - 2141 排队(树状数组套treap||分块)
- bzoj2141【分块+树状数组】
- BZOJ 2141 排队 [分块+树状数组]
- [BZOJ]2141: 排队 分块+树状数组
- [BZOJ]2124 等差子序列 Hash&树状数组
- 【BZOJ4167】永远的竹笋采摘 分块+树状数组
- Bzoj3132 二维树状数组
- 【BZOJ2683】简单题 [分治][树状数组]
- BZOJ 1452: [JSOI2009]Count 二维树状数组
- 【BZOJ】【P1452】【JSOI2009】【Count】【二维树状数组】
- [dfs序 树状数组] BZOJ 1103 [POI2007]大都市meg