一道CDQ分治模板题
简单来说,这道题是三维数点
对于离线的二维数点,我们再熟悉不过:利用坐标的单调递增性,先按更坐标排序,再按纵坐标排序
更新和查询时都直接调用纵坐标。
实际上,我们是通过排序将二维中的一维给消掉了。
那么,对于题中的三维数点,我们可以先按 $x$ 排序,以 $x$ 为标准进行分治
在分治的过程中,分别对左右区间按 $y$ 来排序。
由于左面的 $x$ 坐标一定是小于右面的 $x$ 坐标的。
所以这一维可以被我们消掉。
剩下的就是一个二维数点问题了,只需按照顺序依次更新 $z$ 即可。
(反正左面的 $x$ 比右面小,而且 $y$ 也一定比右面小,只要 $z$ 比右面小是都能统计出来的)

Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
#define maxn 1000006
using namespace std;
int n,m,idx,place[maxn],C[maxn];
long long ans[maxn];
struct BIT{
int lowbit(int x) { return x&(-x); }
void add(int pos,int x){
while(pos<=n) C[pos]+=x,pos+=lowbit(pos);
}
int ask(int pos){
int sum=0;
while(pos>0) sum+=C[pos],pos-=lowbit(pos);
return sum;
}
}tree;
struct OPT{
int x,y,z,rnk,kind,id;
}opt[maxn],tmp[maxn];
bool cmp(OPT i,OPT j)
{
return (i.x==j.x&&i.y==j.y)?(i.rnk<j.rnk):((i.x==j.x)?i.y<j.y:i.x<j.x);
}
void solve(int L,int R)
{
if(L>=R) return;
int mid=(L+R)>>1,tl=L-1,tr=mid;
for(int i=L;i<=R;++i){
if(opt[i].rnk<=mid&&opt[i].kind==1) tree.add(opt[i].y,opt[i].z);
if(opt[i].rnk>mid&&opt[i].kind==2) ans[opt[i].id]+=tree.ask(opt[i].y)*opt[i].z;
}
for(int i=L;i<=R;++i)
if(opt[i].rnk<=mid&&opt[i].kind==1) tree.add(opt[i].y,-opt[i].z);
for(int i=L;i<=R;++i) {
if(opt[i].rnk<=mid) tmp[++tl]=opt[i];
else tmp[++tr]=opt[i];
}
for(int i=L;i<=R;++i) opt[i]=tmp[i];
solve(L,mid),solve(mid+1,R);
}
int main(){
//setIO("input");
scanf("%d%d",&n,&m);
for(int i=1,a;i<=n;++i)
{
scanf("%d",&a);
opt[++idx].x=i;
opt[idx].y=a;
opt[idx].z=1;
opt[idx].kind=1;
opt[idx].rnk=idx;
place[a]=i;
tree.add(a,1);
ans[1]+=i-tree.ask(a);
}
for(int i=1;i<=n;++i) tree.add(i,-1);
for(int i=1,a;i<=m;++i){
scanf("%d",&a);
opt[++idx].x=place[a];
opt[idx].y=n;
opt[idx].z=-1;
opt[idx].kind=2;
opt[idx].rnk=idx;
opt[idx].id=i+1; opt[++idx].x=n;
opt[idx].y=a;
opt[idx].z=-1;
opt[idx].kind=2;
opt[idx].rnk=idx;
opt[idx].id=i+1; opt[++idx].x=place[a];
opt[idx].y=a;
opt[idx].z=2;
opt[idx].kind=2;
opt[idx].rnk=idx;
opt[idx].id=i+1; opt[++idx].x=place[a];
opt[idx].y=a;
opt[idx].z=-1;
opt[idx].kind=1;
opt[idx].rnk=idx;
}
sort(opt+1,opt+1+idx,cmp);
solve(1,idx);
for(int i=2;i<=m;++i) ans[i]+=ans[i-1];
for(int i=1;i<=m;++i) printf("%lld\n",ans[i]);
return 0;
}

  

P3157 [CQOI2011]动态逆序对 CDQ分治的更多相关文章

  1. 洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治

    题目:https://www.luogu.org/problemnew/show/3157 题解: 1.对于静态的逆序对可以用树状数组做 2.我们为了方便可以把删除当成增加,可以化动为静 3.找到三维 ...

  2. LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)

    传送门 解题思路 cdq分治,将位置看做一维,修改时间看做一维,权值看做一维,然后就转化成了三维偏序,用排序+cdq+树状数组.注意算删除贡献时要做两次cdq,分别算对前面和后面的贡献. #inclu ...

  3. P3157 [CQOI2011]动态逆序对 (CDQ解决三维偏序问题)

    P3157 [CQOI2011]动态逆序对 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任 ...

  4. [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...

  5. 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治

    [BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...

  6. bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)

    3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...

  7. BZOJ3295 [Cqoi2011]动态逆序对 —— CDQ分治

    题目链接:https://vjudge.net/problem/HYSBZ-3295 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 1 ...

  8. [CQOI2011]动态逆序对 CDQ分治

    洛谷上有2道相同的题目(基本是完全相同的,输入输出格式略有不同) ---题面--- ---题面--- CDQ分治 首先由于删除是很不好处理的,所以我们把删除改为插入,然后输出的时候倒着输出即可 首先这 ...

  9. BZOJ 3295: [Cqoi2011]动态逆序对 [CDQ分治]

    RT 传送门 首先可以看成倒着插入,求逆序对数 每个数分配时间(注意每个数都要一个时间)$t$,$x$位置,$y$数值 $CDQ(l,r)$时归并排序$x$ 然后用$[l,mid]$的加入更新$[mi ...

随机推荐

  1. java web项目中资源国际化

    有一些网站会有语言栏选项: 选择英文,内容就显示为英文: 选择中文,内容就显示文中文. 这里就用到了国际化资源. 先看效果图: 步骤: 1.建立资源包: mess_en_US.properties ( ...

  2. C#调用GPG命令进行加密解密文件操作

    public void GPG() { string password = "1234567890"; System.Diagnostics.ProcessStartInfo ps ...

  3. KMP算法中求next数组的实质

    在串匹配模式中,KMP算法较蛮力法是高效的算法,我觉得其中最重要的一点就是求next数组: 看了很多资料才弄明白求next数组是怎么求的,我发现我的忘性真的比记性大很多,每次看到KMP算法求next数 ...

  4. JQuery插件的写法 (转:太棒啦!)

    JQuery插件写法的总结 最近Web应用程序中越来越多地用到了JQuery等Web前端技术.这些技术框架有效地改善了用户的操作体验,同时也提高了开发人员构造丰富客户 端UI的效率.JQuery本身提 ...

  5. 使用rman恢复数据小结

    恢复前提有数据备份 以 alter database open resetlogs 开机以后多要做一次全备(以前的备份失效了) 恢复参数文件: restore spfile from '/home/o ...

  6. sftp权限

    用户: t1 t2 根目录: /home/data/ /home/data/t1/ drwxr-xr-x. 2 t1 t1 4096 Mar 24 17:26 t1 /home/data/t2/ dr ...

  7. ActiveMQ学习笔记(3)----JMS的可靠性机制

    1. 消息接收确认 JMS消息只有在被确认之后,才认为已经被成功的消费了,消息成功消费通常包含三个阶段:客户接收消息,客户处理消息和消息被确认. 在事务性会话中,当一个事务被提交的时候,确认自动发生. ...

  8. 路飞学城Python-Day8

    [11.函数-基本介绍]函数引出问题:如果出现这个需求,需要监控单位的服务器状况,当CPU/MEMORY/DISK等指标使用量超过阀值时,就发邮件报警 while True: if CPU利用率> ...

  9. NodeJS学习笔记 (5)网络服务-http-req(ok)

    原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: 概览 本文的重点会放在req这个对象上.前面已经提到,它其实是http.Incom ...

  10. Oracle日期的加减运算

    无论是DATE还是timestamp都可以进行加减操作.可以对当前日期加年.月.日.时.分.秒,操作不同的时间类型,有三种方法: 1 使用内置函数numtodsinterval增加小时,分钟和秒2 加 ...