BZOJ 3295: [Cqoi2011]动态逆序对 (树状数组套主席树)
来源:互联网 发布:ee是哪个国家域名 编辑:程序博客网 时间:2024/05/29 08:29
题面:
对于序列A,它的逆序对数定义为满足
对于已经存在的序列进行删除不是很好操作,不妨先倒过来想,假设我们将这些数空缺,然后倒序加入序列中是否可行,很明显可以,那么剩下的问题就是对于当前加入的书产生了多少个逆序对,对于新添入一个数来说,产生的逆序对一定是当前序列中1~x比它大的和x~n比它小的个数和,很明显这个问题用主席树可以解决,由于下标的顺序问题,不妨用树状数组套一下,建立下标树状数组,这样问题就迎刃而解了。
如果对于每个操作都开logn个结点,那么理论上的空间为
#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 100005int n,m,cnt;long long sum;long long ans[maxn];bool vis[maxn];int b[maxn];int a[maxn],indx[maxn];int root[maxn];void init(){ memset(root,0,sizeof root); memset(vis,false,sizeof vis); cnt=0; sum=0;}struct node{ int l,r; int sum; node() { l=r=sum=0; }} t[90*maxn];void update(int &rt,int pre,int pos,int l,int r){ if(!rt) t[rt=++cnt]=t[pre]; t[rt].sum++; if(l==r&&r==pos) { t[rt].sum=1; return ; } int mid=l+r>>1; if(pos<=mid) update(t[rt].l,t[pre].l,pos,l,mid); else update(t[rt].r,t[pre].r,pos,mid+1,r);}int query1(int rt,int pos,int l,int r){ if(l==r&&r==pos) { return 0; } int mid=l+r>>1; if(pos<=mid) return query1(t[rt].l,pos,l,mid)+t[t[rt].r].sum; else return query1(t[rt].r,pos,mid+1,r);}int query2(int rt,int pos,int l,int r){ if(l==r&&r==pos) { return 0; } int mid=l+r>>1; if(pos<=mid) return query2(t[rt].l,pos,l,mid); else return query2(t[rt].r,pos,mid+1,r)+t[t[rt].l].sum;}int lowbit(int x){ return x&-x;}void add(int x,int pos){ for(; x<=n; x+=lowbit(x)) update(root[x],root[x],pos,1,n);}long long ask(int x,int pos){ long long temp=0; for(int i=x; i>0; i-=lowbit(i)) temp+=query1(root[i],pos,1,n); for(int i=n; i>0; i-=lowbit(i)) temp+=query2(root[i],pos,1,n); for(int i=x; i>0; i-=lowbit(i)) temp-=query2(root[i],pos,1,n); return temp;}int main(){ scanf("%d%d",&n,&m); init(); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); indx[a[i]]=i; } for(int i=0; i<m; i++) { scanf("%d",&b[m-i-1]); vis[b[m-i-1]]=1; } for(int i=1; i<=n; i++) { if(!vis[a[i]]) { add(i,a[i]); sum+=ask(i,a[i]); } } for(int i=0; i<m; i++) { add(indx[b[i]],b[i]); sum+=ask(indx[b[i]],b[i]); ans[i]=sum; } for(int i=m-1; i>=0; i--) { printf("%lld\n",ans[i]); } return 0;}
0 0
- BZOJ 3295: [Cqoi2011]动态逆序对 (树状数组套主席树)
- 3295: [Cqoi2011]动态逆序对 树状数组套主席树
- 【bzoj3295】[Cqoi2011]动态逆序对 树状数组套主席树
- BZOJ 3295 [Cqoi2011]动态逆序对 树状数组套线段树
- 【BZOJ】3295 [Cqoi2011]动态逆序对 树状数组+线段树
- 【bzoj3295】 CQOI2011动态逆序对 树状数组+主席树
- bzoj3295: [Cqoi2011]动态逆序对 树状数组套线段树
- BSOJ2841:CQOI2011动态逆序对 树状数组套平衡树
- 【bzoj3295】【Cqoi2011】【动态逆序对】【树状数组套平衡树】
- bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组
- [bzoj]3295: [Cqoi2011]动态逆序对 主席树
- 主席树初探 & bzoj 3295: [Cqoi2011] 动态逆序对 题解
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- bzoj 3295: [Cqoi2011]动态逆序对 (CDQ分治+树状数组)
- [BZOJ 3295] Cqoi2011 动态逆序对
- 【BZOJ 3295】 [Cqoi2011]动态逆序对
- BZOJ 3295 [Cqoi2011]动态逆序对
- BZOJ 3295 [CQOI2011] 动态逆序对
- ArrayList与HashMap的构建和输出
- 2016多校10 HDU 5860 Death Sequence
- 概率图模型(07): 从思路到模型(Knowledge Engineering)
- socket 通信关于bind那点事
- 遍历Map的四种方法
- BZOJ 3295: [Cqoi2011]动态逆序对 (树状数组套主席树)
- 计蒜客挑战难题:爬楼梯
- Android View滑动
- [例证]从滑动冲突到事件分发(从源码角度分析)
- Android开发笔记之软键盘的隐藏
- js如何判断一个对象是不是Array?
- 字符设备驱动访问原理
- [ERROR] Cannot find or open table wu777/processlist from the internal data dictionary of InnoDB tho
- Android不同api调用显示路径