bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组
来源:互联网 发布:软件开发是什么专业 编辑:程序博客网 时间:2024/05/16 09:39
题目大意
给出1-n的一个排列和m个操作,每个操作有一个数字x表示在序列中把x这个数删掉,并且求在删掉x前该序列中有多少个逆序对。
n<=100000,m<=50000
分析
这题看完题后就想到了可以用树套树来搞,但是比较麻烦(其实也不是很麻烦)并且对于n<=100000,m<=50000的数据范围如果用nlog^2的复杂度去做的话会跑的很慢,于是就选择了新学的cdq分治。
先一开始往序列里面插入没被删除的数,然后从后往前的顺序处理操作。把每个操作拆分成两个操作,一个是插入,一个是询问,顺序不限。
那么问题就转换成了对于三元组(x,y,z)的处理,x是操作序号,y是下标,z是具体数值。对于这种问题一般的处理方式都是第一维直接排序,第二维cdq分治掉,第三维树状数组。
具体的就跟bzoj 3262一样啦。
注意要开long long
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 100005#define ll long longusing namespace std;int c[N],a[N],pos[N],n,m,cnt,tot,vis[N],num[N],ans[N];struct data{int x,pos,op,id;}q[N*10],t[N*10];void ins(int x,int y){ while (x<=n) { c[x]+=y; x+=x&(-x); }}int query(int x){ int ans=0; while (x) { ans+=c[x]; x-=x&(-x); } return ans;}void cdq(int l,int r){ if (l>=r) return; int mid=(l+r)/2; cdq(l,mid);cdq(mid+1,r); for (int j=mid+1,i=l;j<=r;j++) { while (q[i].pos<q[j].pos&&i<=mid) { if (q[i].op==1) ins(q[i].x,1); i++; } if (q[j].op==2) ans[q[j].id]+=query(q[j].x-1); } for (int i=l,j=mid+1;j<=r;j++) while (q[i].pos<q[j].pos&&i<=mid) { if (q[i].op==1) ins(q[i].x,-1); i++; } for (int i=mid,j=r;j>mid;j--) { while (q[i].pos>q[j].pos&&i>=l) { if (q[i].op==1) ins(q[i].x,1); i--; } if (q[j].op==2) ans[q[j].id]+=query(n)-query(q[j].x); } for (int i=mid,j=r;j>mid;j--) while (q[i].pos>q[j].pos&&i>=l) { if (q[i].op==1) ins(q[i].x,-1); i--; } int i=l,j=mid+1,k=l; while (i<=mid||j<=r) if (q[i].pos<q[j].pos&&i<=mid||j>r) t[k++]=q[i++]; else t[k++]=q[j++]; for (int i=l;i<=r;i++) q[i]=t[i];}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); pos[a[i]]=i; } for (int i=1;i<=m;i++) { scanf("%d",&num[i]); vis[pos[num[i]]]=1; } ll sum=0; for (int i=1;i<=n;i++) { sum+=query(n)-query(a[i]); ins(a[i],1); } for (int i=1;i<=n;i++) ins(a[i],-1); for (int i=1;i<=n;i++) if (!vis[i]) { q[++tot].op=1; q[tot].pos=i; q[tot].x=n-a[i]+1; } for (int i=m;i>=1;i--) { q[++tot].op=1; q[tot].pos=pos[num[i]]; q[tot].x=n-num[i]+1; q[++tot].op=2; q[tot].pos=pos[num[i]]; q[tot].x=n-num[i]+1; q[tot].id=++cnt; } cdq(1,tot); for (int i=cnt;i>=1;i--) { printf("%lld\n",sum); sum-=ans[i]; } return 0;}
0 0
- bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组
- bzoj 3295: [Cqoi2011]动态逆序对 (CDQ分治+树状数组)
- [BZOJ3295][CQOI2011]动态逆序对-CDQ分治+树状数组
- bzoj 3295: [Cqoi2011]动态逆序对 【cdq分治】
- BZOJ 3295 [Cqoi2011] 动态逆序对 CDQ分治题解
- 3295: [Cqoi2011]动态逆序对 CDQ分治
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- 【BZOJ】3295 [Cqoi2011]动态逆序对 树状数组+线段树
- [BZOJ3295] [Cqoi2011]动态逆序对 && CDQ分治
- 【CDQ分治】[CQOI2011][NKOJ2041]动态逆序对
- CQOI2011动态逆序对--cdq分治
- BZOJ 3295 动态逆序对 CDQ分治
- bzoj 3295 动态逆序对 CDQ分治
- BZOJ 3295 动态逆序对 CDQ分治
- [BZOJ3295] [Cqoi2011]动态逆序对 (树套树)or(CDQ分治)
- CDQ分治——BZOJ3295/Luogu3157 [CQOI2011]动态逆序对
- cdq分治——P3157 [CQOI2011]动态逆序对
- BZOJ3295: [Cqoi2011]动态逆序对(CDQ分治)
- 2016-2017 ACM-ICPC, NEERC (Online Mirror) 酱油记
- 关于矩阵幂次的求解
- 非常好的讲布局的习题
- Android自定义之仿支付宝支付成功、失败状态的加载进度
- update-grub脚本分析
- bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组
- MATLAB 部分函数在C++中的转化
- AngularJS 简介
- halcon学习笔记——机器视觉工程应用的开发思路
- 第2.1.7章 WEB系统最佳实践Spring文件配置之spring-shiro.xml
- C语言错误处理
- 2016noip普及组初赛答案
- 极其简单的一个JSP小功能
- NOIP2016答案