bzoj 3295 [Cqoi2011]动态逆序对(cdq分治,BIT)
2016-03-08 20:18
337 查看
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=3295
【题意】
n个元素依次删除m个元素,求删除元素之前序列有多少个逆序对。
【思路】
cdq分治
这个题转化一下可以变成刚刚做过的三维偏序。
首先有两个量:序 和 值,可以将样例写成
x 1
2 3 4 5
y 1 5
3 4 2
然后因为我们要删除一些东西,所以加上时间,则样例变为
t 1 2
3 4 5
x 3 5
4 1 2
y 3 2
4 1 5
删除顺序就是按照t从大到小。我们把它看作t从小到大的插入结点。
则我们要求的是,一个结点在t时刻插入,左边有多少个比它大,右边有多少个比它小,设这个点为(t0,x0,y0),则我们要求的就是满足
t<t0,x<x0,y>y0
t<t0,x>x0,y<y0
的点数。因为具体的值对结果并无影响我们可以通过把a改成n-a+1来改变符号的方向,具体就是求满足
t<t0,x<x0,y<(n-y0+1)
t<t0,x<(n-x0+1),y<y0
的点数。
于是问题变成了刚做过的
陌上花开 问题。
最后统计每个时间点发生之前产生的所有逆序对。
【代码】
http://www.lydsy.com/JudgeOnline/problem.php?id=3295
【题意】
n个元素依次删除m个元素,求删除元素之前序列有多少个逆序对。
【思路】
cdq分治
这个题转化一下可以变成刚刚做过的三维偏序。
首先有两个量:序 和 值,可以将样例写成
x 1
2 3 4 5
y 1 5
3 4 2
然后因为我们要删除一些东西,所以加上时间,则样例变为
t 1 2
3 4 5
x 3 5
4 1 2
y 3 2
4 1 5
删除顺序就是按照t从大到小。我们把它看作t从小到大的插入结点。
则我们要求的是,一个结点在t时刻插入,左边有多少个比它大,右边有多少个比它小,设这个点为(t0,x0,y0),则我们要求的就是满足
t<t0,x<x0,y>y0
t<t0,x>x0,y<y0
的点数。因为具体的值对结果并无影响我们可以通过把a改成n-a+1来改变符号的方向,具体就是求满足
t<t0,x<x0,y<(n-y0+1)
t<t0,x<(n-x0+1),y<y0
的点数。
于是问题变成了刚做过的
陌上花开 问题。
最后统计每个时间点发生之前产生的所有逆序对。
【代码】
#include<cstdio> #include<iostream> #include<algorithm> #define rep(a,b,c) for(int a=b;a<=c;++a) using namespace std; typedef long long ll; const int N =3*1e5+10; void read(int &x) { char c=getchar(); x=0; while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); } struct Node { int a,b,c,ans; bool operator<(const Node& rhs) const { return a<rhs.a; } }q ,T ; bool cmp(const Node& x,const Node& y) { return x.b<y.b||(x.b==y.b&&x.c>y.c); } int n,m,mx,C ,rk ; ll ans ; void add(int x,int v) { for(;x<=mx;x+=x&-x) C[x]+=v; } int query(int x) { int res=0; for(;x;x-=x&-x) res+=C[x]; return res; } void solve(int l,int r) { if(l==r) return ; int mid=(l+r)>>1; solve(l,mid) , solve(mid+1,r); int l1=l,l2=mid+1,i; while(l2<=r) { while(l1<=mid&&q[l1].b<q[l2].b) { add(q[l1].c,1); l1++; } q[l2].ans+=query(q[l2].c); l2++; } for(i=l;i<l1;i++) add(q[i].c,-1); l1=l,l2=mid+1; int now=l; while(l1<=mid||l2<=r) { if(l2>r||l1<=mid&&cmp(q[l1],q[l2])) T[now++]=q[l1++]; else T[now++]=q[l2++]; } for(int i=l;i<=r;i++) q[i]=T[i]; } int main() { read(n),read(m); mx=n+5; rep(i,1,n) { q[i].b=i; read(q[i].c); } int a; rep(i,1,m) { read(a); rk[a]=i; } int sz=m; rep(i,1,n) if(!rk[i]) rk[i]=++sz; rep(i,1,n) q[i].a=n-rk[q[i].c]+1; sort(q+1,q+n+1); rep(i,1,n) q[i].b=n-q[i].b+1; solve(1,n); sort(q+1,q+n+1); rep(i,1,n) { q[i].b=n-q[i].b+1; q[i].c=n-q[i].c+1; } solve(1,n); rep(i,1,n) ans[q[i].a]=q[i].ans; rep(i,1,n) ans[i]+=ans[i-1]; for(int i=n;i>n-m;i--) printf("%lld\n",ans[i]); return 0; }
相关文章推荐
- java继承知识
- codeforces 106C. Buns【多重背包】
- LIBSVM python
- UITableView 单元格自定义个别不能滑动删除
- python Django + uwsgi + nginx 在阿里云Ubuntu环境下的部署
- 表格自动换行等前端技能
- ACM2014
- 66. Plus One
- 关于datetime-local与时间戳相互转化
- NYOJ5056_黑色帽子(水题)
- Java IO——File类
- 关于TimePickerDialog里的取消按钮
- 调整数组顺序使得奇数位于偶数前面
- vultr vps服务器存在的7个优势及选择原因
- Java设计模式学习笔记(观察者模式)
- python 压缩
- 【CODEVS1033】蚯蚓的游戏问题(费用流)
- Unity3D启动报错的解决方案
- 第1周项目2—就拿胖子说事
- 第二周项目2-就拿胖子说事