CDQ 分治算法模板
CDQ分治
1.三维偏序问题:三维偏序(陌上花开)
#include<bits/stdc++.h>
#define RG register
#define IL inline
#define _ 200005
using namespace std;
IL int gi(){
RG int data = 0 , m = 1; RG char ch = 0;
while(ch != '-' && (ch<'0'||ch>'9'))ch = getchar();
if(ch == '-'){m = -1; ch = getchar();}
while('0'<=ch && ch<='9')
data = (data<<3) + (data<<1) + (ch - '0') , ch = getchar();
return (m) ? data : -data;
}
int tot,bt[_],n,k,f[_],g[_],blg[_]; long long ans[_];
struct Node{
int a, b, c , w , id;
//w记录这个节点对应多少个真实节点,id则是其对应编号.
bool operator <(const Node &B)const{
return (b == B.b) ? c <= B.c : b < B.b;}
};
Node q1[_],q[_],tmp[_];
namespace BIT{
IL void Update(RG int ps,RG int dt){
for(RG int i = ps; i <= k; i += (i&-i))bt[i] += dt;
}
IL void Clear(RG int ps){
for(RG int i = ps; i <= k; i += (i&-i))bt[i] = 0;
}
IL int Query(RG int ps){
RG int res = 0;
for(RG int i = ps; i > 0; i -= (i&-i))res += bt[i];
return res;
}
}
void cdq(RG int L,RG int R){
if(L == R)return;
RG int mid = (L+R)>>1; cdq(L,mid); cdq(mid+1,R);
RG int l = L , r = mid+1 , oo = L-1;
while(l <= mid && r <= R){
if(q[l] < q[r])
BIT::Update(q[l].c,q[l].w) ,
tmp[++oo] = q[l++];
else
g[q[r].id] += BIT::Query(q[r].c) ,
tmp[++oo] = q[r++];
}
while(l <= mid)tmp[++oo] = q[l++];
while(r <= R)
g[q[r].id] += BIT::Query(q[r].c) ,
tmp[++oo] = q[r++];
for(RG int i = L; i <= R; i ++)
BIT::Clear(tmp[i].c) , q[i] = tmp[i];
return;
}
IL bool cmp(Node a,Node b){
if(a.a != b.a)return a.a < b.a;
if(a.b != b.b)return a.b < b.b;
if(a.c != b.c)return a.c < b.c;
return a.id < b.id; //注意:这里一定要随便定义一个优先级
}
IL bool Equl(int nw,int cp){
if(!cp)return false;
else return (q1[nw].a==q[cp].a &&
q1[nw].b==q[cp].b && q1[nw].c==q[cp].c);
}
int main(){
n = gi(); k = gi();
for(RG int i = 1,a,b,c; i <= n; i ++)
a = gi(),b = gi(),c = gi(),
q1[i] = (Node){a , b , c , 1 , i};
//去重:
tot = 0;
sort(q1+1,q1+n+1,cmp);
for(RG int i = 1; i <= n; i ++){
if(!Equl(i,tot))
q[++tot] = q1[i] , q[tot].w = 1 , q[tot].id = tot;
else q[tot].w ++;
blg[i] = tot; //记录i点是对应去重后的哪个节点
}
cdq(1,tot);
// f[i] 表示去重前点i满足 (aj<=ai,bj<=bi,cj<=ci) 的j的个数.
// g[i] 表示去重后点i满足条件的j的个数
for(RG int i = 1; i <= tot; i ++)g[q[i].id] += q[i].w-1;
for(RG int i = 1; i <= n; i ++)f[i] = g[blg[i]];
for(RG int i = 1; i <= n; i ++)ans[f[i]] ++;
for(RG int i = 0; i < n; i ++)printf("%lld\n",ans[i]);
return 0;
}
2.动态逆序对问题:[CQOI2011]动态逆序对
#include<bits/stdc++.h>
#define RG register
#define IL inline
#define _ 300005
using namespace std;
IL int gi(){
RG int data = 0 , m = 1; RG char ch = 0;
while(ch != '-' && (ch<'0'||ch>'9'))ch = getchar();
if(ch == '-'){m = -1; ch = getchar();}
while('0'<=ch && ch<='9')
data = (data<<3) + (data<<1) + (ch - '0') , ch = getchar();
return (m) ? data : -data;
}
struct Query{
int tm , ps , val;
bool operator < (const Query &B)const{ return ps < B.ps; }
};
Query q[_] , tmp[_];
int ans[_],bt[_],n,m,pos[_]; long long Ans; bool vis[_];
namespace BIT{
IL void Update(RG int ps,RG int dt){
for(RG int i = ps; i <= n; i += (i&-i))bt[i] += dt;
}
IL int Query(RG int ps){
RG int res = 0;
for(RG int i = ps; i > 0; i -= (i&-i))res += bt[i];
return res;
}
}
void cdq(RG int L,RG int R){
if(L == R)return;
RG int mid = (L+R)>>1; cdq(L,mid); cdq(mid+1,R);
RG int l = L , r = mid+1 , oo = L-1;
while(l<=mid && r<=R)
if(q[l] < q[r])tmp[++oo] = q[l++]; else tmp[++oo] = q[r++];
while(l<=mid)tmp[++oo] = q[l++];
while(r<=R)tmp[++oo] = q[r++];
for(RG int i = L; i <= R; i ++)q[i] = tmp[i];
//get - behind - smaller
for(RG int i = L; i <= R; i ++)
if(q[i].tm <= mid)BIT::Update(q[i].val,1);
else ans[q[i].tm] += BIT::Query(n) - BIT::Query(q[i].val);
for(RG int i = L; i <= R; i ++)
if(q[i].tm <= mid)BIT::Update(q[i].val,-1);
//get - front - bigger
for(RG int i = R; i >= L; i --)
if(q[i].tm <= mid)BIT::Update(q[i].val,1);
else ans[q[i].tm] += BIT::Query(q[i].val);
for(RG int i = R; i >= L; i --)
if(q[i].tm <= mid)BIT::Update(q[i].val,-1);
return;
}
IL bool cmp(Query a,Query b){return a.tm<b.tm;}
int main(){
n = gi(); m = gi();
RG int tot = 0;
for(RG int u,i = 1; i <= n; i ++)
u = gi() , pos[u] = i , vis[u] = 1;
for(RG int u,i = n; i >= n-m+1; i --)
u = gi() , vis[u] = 0 ,
q[++tot] = (Query){i,pos[u],u};
RG int cnt = n - m + 1;
for(RG int i = 1; i <= n; i ++)
if(vis[i])q[++tot] = (Query){--cnt,pos[i],i};
sort(q+1,q+tot+1,cmp);
cdq(1,tot);
Ans = 0;
for(RG int i = 1; i <= n; i ++)Ans += ans[i];
for(RG int i = n; i >= n-m+1; i --)
printf("%lld\n",Ans) , Ans -= ans[i];
return 0;
}
离线修改与查询问题:树状数组 1
#include<bits/stdc++.h>
#define RG register
#define IL inline
#define ll long long
#define _ 4*500005
using namespace std;
int n,m,ask,tot; ll ans[_];
struct Do{
int typ,pos,val;
bool operator <(const Do &B)const{
return (pos == B.pos)?typ < B.typ : pos < B.pos; }
};
Do q[_],tmp[_];
void cdq(RG int L,RG int R){
if(L == R)return;
RG int mid = (L+R)>>1; cdq(L,mid); cdq(mid+1,R);
RG ll upt = 0 , l = L , r = mid+1 , oo = 0;
while(l <= mid && r <= R){
if(q[l] < q[r]){
if(q[l].typ == 1)upt += q[l].val;
tmp[++oo] = q[l++];
}
else {
if(q[r].typ == 2)ans[q[r].val] -= upt;
if(q[r].typ == 3)ans[q[r].val] += upt;
tmp[++oo] = q[r++];
}
}
while(l <= mid){
if(q[l].typ == 1)upt += q[l].val;
tmp[++oo] = q[l++];
}
while(r <= R){
if(q[r].typ == 2)ans[q[r].val] -= upt;
if(q[r].typ == 3)ans[q[r].val] += upt;
tmp[++oo] = q[r++];
}
for(RG int i = L; i <= R; i ++)q[i] = tmp[i-L+1];
}
int main(){
scanf("%d %d",&n,&m);
for(RG int i = 1,ww; i <= n; i ++)
scanf("%d",&ww), q[++tot] = (Do){1,i,ww};
ask = 0;
for(RG int i = 1,tp,ps,ww; i <= m; i ++){
scanf("%d %d %d",&tp,&ps,&ww);
if(tp == 1)q[++tot] = (Do){1,ps,ww};
else
q[++tot] = (Do){2,ps-1,++ask} ,
q[++tot] = (Do){3,ww,ask};
}
cdq(1,tot);
for(RG int i = 1; i <= ask; i ++)cout<<ans[i]<<endl;
return 0;
}
CDQ 分治算法模板的更多相关文章
- CDQ分治嵌套模板:多维偏序问题
CDQ分治2 CDQ套CDQ:四维偏序问题 题目来源:COGS 2479 偏序 #define LEFT 0 #define RIGHT 1 struct Node{int a,b,c,d,bg;}; ...
- P3810 【模板】三维偏序(陌上花开)cdq分治
传送门:https://www.luogu.org/problemnew/show/P3810 cdq分治的模板题,第一层外部排序,第二层cdq归并排序,这个时候不用考虑第一次的顺序,第三次用树状数组 ...
- CDQ分治学习笔记
数据结构中的一块内容:$CDQ$分治算法. $CDQ$显然是一个人的名字,陈丹琪(NOI2008金牌女选手) 这种离线分治算法被算法界称为"cdq分治" 我们知道,一个动态的问题一 ...
- 『cdq分治和多维偏序问题』
更新了三维偏序问题的拓展 cdq分治 \(cdq\)分治是一种由\(IOI\ Au\)选手\(cdq\)提出的离线分治算法,又称基于时间的分治算法. 二维偏序问题 这是\(cdq\)分治最早提出的时候 ...
- 初学CDQ分治-NEU1702
关于CDQ分治,首先需要明白分治的复杂度. T(n) = 2T(n/2)+O(kn), T(n) = O(knlogn) T(n) = 2T(n/2)+O(knlogn), T(n) = O(knlo ...
- CDQ分治入门 + 例题 Arnooks's Defensive Line [Uva live 5871]
CDQ分治入门 简介 CDQ分治是一种特别的分治方法,它由CDQ(陈丹琦)神犇于09国家集训队作业中首次提出,因此得名.CDQ分治属于分治的一种.它一般只能处理非强制在线的问题,除此之外这个算法作为某 ...
- 【BZOJ4237】 稻草人 CDQ分治+单调栈
## 题目描述 JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下 ...
- 模板:CDQ分治
UPD:18.06.15修正一些错误,感谢评论区巨佬orz CDQ分治不是一个顾名思义的东西,CDQ分治是为了纪念神犇陈丹琦而命名的一种算法. 那么CDQ分治能干什么?CDQ分治主要是用来解决一类”操 ...
- 【算法学习】【洛谷】cdq分治 & P3810 三维偏序
cdq是何许人也?请参看这篇:https://wenku.baidu.com/view/3b913556fd0a79563d1e7245.html. 在这篇论文中,cdq提出了对修改/询问型问题(Mo ...
随机推荐
- asp.net Global.asax 不运行解决
asp.net application的站点发布后 Global.asax 未运行,搞了好久终于解决, 解决方法如下: publish设置 该设置经测试在win server 2003 和2008 都 ...
- 不受支持的URL Statue Code 1002
1. 错误提示: Error description=Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" User ...
- python学习:设计一个算法将缺失的数字找出来。
算法题 已知整型数值 a[99], 包含的所有99个元素都是从1-100中随机取值,并且这99个数两两互不相等,也就是说从1到100这100个数字有99个在数值内,有一个缺失.请设计一个算法将缺失 ...
- [poj3565]Ants
[poj3565]Ants 标签(空格分隔):二分图 描述 Young naturalist Bill studies ants in school. His ants feed on plant-l ...
- 怎么添加用户到sudo用户组
跨平台系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#linux 前段时间用Ubuntu的sudo用惯了,回到kali发现自己的用户太low了, ...
- JavaScript那些事
1.定义静态常量: const C=1; 该常量不能变化的. 2.在if判断中如果是两个变量比较js会将一个字符和一个数字比较的话,会将字符转换成数字然后在对这两个进行对比: var num= ...
- Mysql 远程登录及常用命令
第一招.mysql服务的启动和停止 net stop mysql net start mysql 第二招.登陆mysql 语法如下: mysql -u用户名 -p用户密码 键入命令mysql -uro ...
- iOS中的定时器
据我所知,iOS中的定时器有两种.一个叫NSTimer,一个叫CADisplayLink.还有一种是使用GCD,不常用,这里就不介绍了. 下边说下两个定时器分别得用法: =============== ...
- Centos下安装php扩展sphinx
官方地址:http://pecl.php.net/package/sphinx wget http://pecl.php.net/get/sphinx-1.3.3.tgz tar -zxvf sphi ...
- java复习笔记
本笔记(无异常处理与网络编程部分)整理自<java程序设计>-黄岚 王岩 王康平 编著 java数据 UI I/O java线程 数据库操作 Java数 ...