【cdq分治】[HYSBZ/BZOJ3295]动态逆序对
来源:互联网 发布:js隐藏显示div 编辑:程序博客网 时间:2024/05/17 23:13
题目
看看这篇博客写的时间,BZOJ已经挂了,我就不粘BZOJ链接了。
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
Sample Output
5
2
2
1
Hint
样例解释
(1,5,3,4,2)>>(1,3,4,2)>>(3,4,2)>>(3,2)>>(3)。
数据范围
编号 1-2 3-4 5-6 7-8 9-10
n <=1000 <=30000 <=50000 <=60000 <=100000
m <=100 <=10000 <=20000 <=40000 <=50000
分析
这道题
我们令y表示当前数字,t表示y被加入(先被删除的后加入)的时间,x表现y在原串中的位置,这样一个数字就变成了一个三元组(t,x,y)。
不难发现,当一个数字(t0,x0,y0)对最终的逆序对数作出的贡献为存在的三元组(t,x,y)使得
这样,我们就可以用cdq分治做这道题。
如果你已经会cdq请直接看代码。
如何用cdq分治做这道题
This part was powered by azui
即
我们先考虑满足条件一:
在外面按x排序后,还剩下t,y两个参数。我们可以对t进行划分排序,使得t,x满足。
然后就可以求出对于每一个右边的三元组(t0,x0,y0),有多少个点满足
条件二类似。
然后递归处理左右两边。
感谢azui大神,你们也可以去看他自己的博客。
代码
#include<cstdio>#include<algorithm>#define MAXN 100000using namespace std;struct node{ int t,x,y; node(){ } node(int tt,int xx,int yy){ t=tt,x=xx,y=yy; }}p[MAXN+10],tmp[MAXN+10];int n,m,a[MAXN+10],t[MAXN+10],c[MAXN+10];long long ans[MAXN+10];void Read(int &x){ char c; while(c=getchar(),c!=EOF) if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); return; }}inline int lowbit(int x){ return x&-x;}void update(int x,int d){ while(x<=n){ c[x]+=d; x+=lowbit(x); }}int get_sum(int x){ int ret=0; while(x){ ret+=c[x]; x-=lowbit(x); } return ret;}void read(){ Read(n),Read(m); int i,b,j=0; for(i=1;i<=n;i++) Read(a[i]); for(i=1;i<=m;i++){ Read(b); t[b]=i; } for(i=1;i<=n;i++) if(t[a[i]]) p[i]=node(n-t[a[i]]+1,i,a[i]); else p[i]=node(++j,i,a[i]);}void cdq(int l,int r){ if(l==r) return; int mid=(l+r)>>1,i,j,k; k=mid+1,j=l; for(i=l;i<=r;i++) if(p[i].t<=mid) tmp[j++]=p[i]; else tmp[k++]=p[i]; for(i=l;i<=r;i++) p[i]=tmp[i]; i=l; for(j=mid+1;j<=r;j++){ for(;i<=mid&&p[i].x<p[j].x;i++) update(p[i].y,1); ans[p[j].t]+=(i-l)-get_sum(p[j].y); } for(i--;i>=l;i--) update(p[i].y,-1); i=mid; for(j=r;j>mid;j--){ for(;i>=l&&p[i].x>p[j].x;i--) update(p[i].y,1); ans[p[j].t]+=get_sum(p[j].y); } for(i++;i<=mid;i++) update(p[i].y,-1); cdq(l,mid); cdq(mid+1,r);}void print(){ int i; for(i=2;i<=n;i++) ans[i]+=ans[i-1]; for(i=n;i>n-m;i--) printf("%I64d\n",ans[i]);}int main(){ read(); cdq(1,n); print();}
- 【cdq分治】[HYSBZ/BZOJ3295]动态逆序对
- [BZOJ3295] [Cqoi2011]动态逆序对 && CDQ分治
- 【bzoj3295】动态逆序对 CDQ分治
- [BZOJ3295]动态逆序对CDQ分治
- [BZOJ3295] [Cqoi2011]动态逆序对 (树套树)or(CDQ分治)
- 【BZOJ3295】动态逆序对,CDQ分治/BIT套权值线段树
- CDQ分治——BZOJ3295/Luogu3157 [CQOI2011]动态逆序对
- [BZOJ3295][CQOI2011]动态逆序对-CDQ分治+树状数组
- BZOJ3295: [Cqoi2011]动态逆序对(CDQ分治)
- bzoj3295 [Cqoi2011]动态逆序对(CDQ分治)
- bzoj3295[Cqoi2011]动态逆序对(cdq分治||可持久化线段树)
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- 整体二分&CDQ分治:[BZOJ2527][POI2011] meteors [BZOJ3295][CQOI2011] 动态逆序对
- 【BZOJ3295】动态逆序对(CQOI2011)-CDQ分治:三维偏序
- bzoj3295[Cqoi2011]动态逆序对 cdq分治(树套树/主席树)
- BZOJ3295:[Cqoi2011]动态逆序对 (BIT套treap/CDQ分治+BIT)
- BZOJ 3295 动态逆序对 CDQ分治
- 【CDQ分治】[CQOI2011][NKOJ2041]动态逆序对
- 浅谈并发与并行
- Android中自动连接到指定SSID的Wi-Fi
- CentOS环境变量设置
- Android常用开源工具(2)-Dagger2进阶
- linphone 分析2 接电话的过程1(mediastream角度解析)
- 【cdq分治】[HYSBZ/BZOJ3295]动态逆序对
- 安卓内存泄露成因和解决办法
- android之wifi开发
- 解决!HTML中head里的内容经浏览器解析后全到body里了
- css srpites css精灵
- perl 对象 通过bless实现
- windows下gitbash可以连接但是idea无法连接的问题
- 三层-架构星星之火
- [NOIP2010]导弹拦截 T3 贪心