P3157 [CQOI2011]动态逆序对 CDQ分治
一道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分治的更多相关文章
- 洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治
题目:https://www.luogu.org/problemnew/show/3157 题解: 1.对于静态的逆序对可以用树状数组做 2.我们为了方便可以把删除当成增加,可以化动为静 3.找到三维 ...
- LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)
传送门 解题思路 cdq分治,将位置看做一维,修改时间看做一维,权值看做一维,然后就转化成了三维偏序,用排序+cdq+树状数组.注意算删除贡献时要做两次cdq,分别算对前面和后面的贡献. #inclu ...
- P3157 [CQOI2011]动态逆序对 (CDQ解决三维偏序问题)
P3157 [CQOI2011]动态逆序对 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任 ...
- [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...
- 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治
[BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...
- bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)
3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...
- BZOJ3295 [Cqoi2011]动态逆序对 —— CDQ分治
题目链接:https://vjudge.net/problem/HYSBZ-3295 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 1 ...
- [CQOI2011]动态逆序对 CDQ分治
洛谷上有2道相同的题目(基本是完全相同的,输入输出格式略有不同) ---题面--- ---题面--- CDQ分治 首先由于删除是很不好处理的,所以我们把删除改为插入,然后输出的时候倒着输出即可 首先这 ...
- BZOJ 3295: [Cqoi2011]动态逆序对 [CDQ分治]
RT 传送门 首先可以看成倒着插入,求逆序对数 每个数分配时间(注意每个数都要一个时间)$t$,$x$位置,$y$数值 $CDQ(l,r)$时归并排序$x$ 然后用$[l,mid]$的加入更新$[mi ...
随机推荐
- MongoDB数据修改案例
数据更新操作 队友MongoDB而言,数据更新是一件非常麻烦的事情.Mongo通常会存副本数据,数据有变更的时候,最好的做法是删除MongoDB的数据,重新插入. Mongo中提供了两个函数,一个是s ...
- linux操作系统下完全删除oracle数据库
1.关掉oracle server 和 background processes ps -ef | grep ora 关掉数据库 shutdown immediate 2.关掉监听 lsnrctl ...
- systemd服务管理---systemctl命令列出所有服务
1.列出系统所有服务 #systemctl list-units --all --type=service
- 在CentOS下安装tomcat并配置环境变量(改默认端口8080为8081)
不多说,直接上干货! 第一步:下载tomcat压缩包 http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.73/bin/ 第二步:上传tomcat压 ...
- js 40 个技巧
1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键<table border oncontextmenu= ...
- python面向对象的成员、属性等
#类成员: #字段 self.xy =qq . xy=qq #普通字段 (保存在对象里面) #直接通过点(.)+ 字段 进行调用 #静态字段 (保存在类里面) #静态字段属于类,在内存只保留一份 . ...
- exsi中的虚拟机添加磁盘后虚拟机中磁盘不出现
exsi中的虚拟机添加磁盘后虚拟机中磁盘不出现解决: 计算机---> 管理: 这里可以选择磁盘,格式,分区, 改盘符等操作
- Dapper基础知识二
在下刚毕业工作,之前实习有用到Dapper?这几天新项目想用上Dapper,在下比较菜鸟,这块只是个人对Dapper的一种总结. 2,如何使用Dapper? 首先Dapper是支持多种数据库的 ...
- c标签迭代Map
<%@ page import="java.util.Map" %> <%@ page import="java.util.HashMap" ...
- linux指令--用户和工作组管理
>>前言 Linux是一个多用户.多任务的操作系统,Linux系统的初衷之一就是满足多用户同时工作的需求,因此,linux需要具备很好的安全性,需要对用户进行管理,用户又分几种,管理 ...