【bzoj3295】【Cqoi2011】【动态逆序对】【树状数组套平衡树】
来源:互联网 发布:大数据赚钱 编辑:程序博客网 时间:2024/05/17 04:58
Description
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
Input
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
Output
输出包含m行,依次为删除每个元素之前,逆序对的个数。
Sample Input
5 4
1
5
3
4
2
5
1
4
2
1
5
3
4
2
5
1
4
2
Sample Output
5
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
HINT
N<=100000 M<=50000
题解:
可以求出一开始的逆序对个数
删除一个数相当于减少了这个数之前比这个数大的数和这个数之后比这个数小的数.
这个可以用树套树来处理.
线段树套平衡树应该是会T,改成树状数组套平衡树就可以了.
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#define N 100010using namespace std;int a[N],root[N<<2],ls[N*30],rs[N*30],t[N],p[N],sz,n,m,tmp,x,tt;long long ans;struct treap{int s,w,rd,v;}tr[N*30];int read(){ int x(0); char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}void add(int x){for (int i=x;i<=n;i+=i&(-i)) t[i]++;}int que(int x){ int ans(0); for (int i=x;i;i-=i&(-i)) ans+=t[i]; return ans;}void update(int k){ tr[k].s=tr[ls[k]].s+tr[rs[k]].s+tr[k].w;}void lturn(int &k){ int t=rs[k];rs[k]=ls[rs[k]];ls[t]=k; update(k);update(t);k=t;} void rturn(int &k){ int t=ls[k];ls[k]=rs[ls[k]];rs[t]=k; update(k);update(t);k=t;}void insert(int &k,int v){ if (!k){k=++sz;tr[k].s=tr[k].w=1;tr[k].v=v;tr[k].rd=rand();return;} if (tr[k].v==v) tr[k].w++; else if (v<tr[k].v){insert(ls[k],v);if (tr[ls[k]].rd<tr[k].rd) rturn(k);} else{insert(rs[k],v);if (tr[rs[k]].rd<tr[k].rd) lturn(k);} update(k); }void del(int &k,int v){ if (!k) return; if (tr[k].v==v){ if (tr[k].w>1) tr[k].w--; else{ if (ls[k]*rs[k]==0) k=ls[k]+rs[k]; else if (tr[ls[k]].rd<tr[k].rd){rturn(k);del(k,v);} else {lturn(k);del(k,v);} } } else if (v<tr[k].v) del(ls[k],v); else del(rs[k],v); update(k);}void build(int x,int v){for (int i=x;i<=n;i+=i&(-i)) insert(root[i],v);}void after(int k,int v){ if (!k) return; if (tr[k].v==v) tmp+=tr[rs[k]].s; else if (v<tr[k].v){tmp+=tr[k].w+tr[rs[k]].s;after(ls[k],v);} else after(rs[k],v);}void pre(int k,int v){ if (!k) return; if (tr[k].v==v) tmp+=tr[ls[k]].s; else if (v<tr[k].v) pre(ls[k],v); else{tmp+=tr[k].w+tr[ls[k]].s;pre(rs[k],v);}}void getafter(int x,int v){ for (int i=x;i;i-=i&(-i)) after(root[i],v);}void getpre(int x,int v){ for (int i=x;i;i-=i&(-i)) pre(root[i],v);}void change(int x,int v){for (int i=x;i<=n;i+=i&(-i)) del(root[i],v);}int main(){ n=read();m=read(); for (int i=1;i<=n;i++) a[i]=read(),p[a[i]]=i; for (int i=1;i<=n;i++) build(i,a[i]); for (int i=n;i>=1;i--){ans+=que(a[i]);add(a[i]);} for (int i=1;i<=m;i++){ x=read(); printf("%lld\n",ans); tmp=0;getafter(p[x],x);ans-=tmp; tmp=0;getpre(n,x);tt=tmp; tmp=0;getpre(p[x],x);ans-=tt-tmp;change(p[x],x); } }
0 0
- 【bzoj3295】【Cqoi2011】【动态逆序对】【树状数组套平衡树】
- bzoj3295: [Cqoi2011]动态逆序对 树状数组套线段树
- 【bzoj3295】[Cqoi2011]动态逆序对 树状数组套主席树
- BSOJ2841:CQOI2011动态逆序对 树状数组套平衡树
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- 【bzoj3295】 CQOI2011动态逆序对 树状数组+主席树
- [BZOJ3295][CQOI2011]动态逆序对-CDQ分治+树状数组
- 3295: [Cqoi2011]动态逆序对 树状数组套主席树
- 【树状数组+线段树动态开点】BZOJ3295(Cqoi2011)[动态逆序对]题解
- 【CQOI2011】【BZOJ3295】动态逆序对
- BZOJ3295 CQOI2011 动态逆序对
- [BZOJ3295] [Cqoi2011]动态逆序对
- 【bzoj3295】[Cqoi2011]动态逆序对
- bzoj3295: [Cqoi2011]动态逆序对
- bzoj3295【CQOI2011】动态逆序对
- 【Cqoi2011】【BZOJ3295】动态逆序对
- bzoj3295: [Cqoi2011]动态逆序对
- [BZOJ3295][Cqoi2011]动态逆序对
- C++复习3.继承的相关概念
- leetcode:Move Zeroes
- 2016计蒜客初赛第一场 青云的机房组网方案(困难):图论+虚树+容斥
- IIS7.0 验证码不显示的解决方案
- 进程状态改变及其原因
- 【bzoj3295】【Cqoi2011】【动态逆序对】【树状数组套平衡树】
- LCD驱动程序移植
- 数据结构与算法复习笔记--排序算法
- ImagePicker 图片选择控件
- IT部门如何摆脱不堪重负的局面?
- struts2+hibernate4+spring4的整合demo
- 四六级写作模板
- iOS内购的开发和坑
- 摘抄某女同学的博客,因为是博客园的没法转载,只好搬运,自愧不如