一道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. Oracle RAC --安装图解

    规划:所用linux系统以虚拟化方式安装在esx上,配置有内网的yum源,各分配有16G存储,下面为简单拓扑图 一,下载软件1,地址:http://www.oracle.com/technology/ ...

  2. [JZOJ NOIP2018模拟10.20 A组]

    由于T3数据出锅,还不清楚自己的分数...估分150,前100已经拿到了,T3的50没拍过(写的就是暴力怎么拍),感觉很不稳 考试的时候就是特别的困,大概是因为早上在房间里腐败...腐败完了才睡觉 T ...

  3. [雅礼NOIP2018集训 day4]

    感觉状态极差啊,今天居然爆零了 主要是以下原因: 1.又是T1看错题肝了两个小时,发现题意理解错误瞬间心态爆炸 2.T2交错了文件名 3.T3暴力子任务和正解(假的)混在一起,输出了两个答案 都想为自 ...

  4. POJ 3299 模拟

    水题,但是WA了一屏--- swap的时候忘了把读入的数字也swap了---------..[尴尬] // by SiriusRen #include <cmath> #include & ...

  5. MyBatis数据持久化(二)建立数据库会话

    上篇文章中介绍了我们使用mybatis前的准备工作,并在程序中通过jdbc与mysql数据库成功建立连接,接下来介绍如何使用mybatis与数据库建立会话.我们需要以下几个步骤: 1.在build p ...

  6. HDU 1394 Minimum Inversion Number【 树状数组 】

    题意:给出n个数,每次可以把第一个数挪到最后一个位置去,问这n种排列里面的最小逆序对数 先把最开始的逆序对数求出来 然后对于一个数a[i],比它小的数有a[i] - 1个,比它大的数有n - a[i] ...

  7. IIS支持10万个同时请求的设置

    1. 调整IIS 7应用程序池队列长度 由原来的默认1000改为65535. IIS Manager > ApplicationPools > Advanced Settings Queu ...

  8. /etc/rsyncd.conf

    [root@backup ~]# cat /etc/rsyncd.conf #Rsync server#created by oldboy ##rsyncd.conf start##uid = rsy ...

  9. 紫书 习题 8-16 UVa 1618 (中途相遇法)

    暴力n的四次方, 然而可以用中途相遇法的思想, 分左边两个数和右边两个数来判断, 最后合起来判断. 一边是n平方logn, 合起来是n平方logn(枚举n平方, 二分logn) (1)两种比较方式是相 ...

  10. [luogu] P4514 上帝造题的七分钟 (树状数组,二维差分)

    P4514 上帝造题的七分钟 题目背景 裸体就意味着身体. 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a ...