首页 > 其他分享 >CDQ 分治

CDQ 分治

时间:2023-07-11 16:46:08浏览次数:42  
标签:le int 分治 mid solve CDQ id

CDQ 分治的思想最早由 IOI2008 金牌得主陈丹琦在高中时整理并总结,因此得名。

适用范围

多用于统计有特征的点对 \((i,j)\) 的数量或找出有特征的点对。

流程

对于一个区间 \([L,R]\) 中的点对 \((i,j)\)(\(L\le i<j\le R\)),考虑分为三部分(\(mid=\frac{L+R}2\)):

  • \(L\le i<j\le mid\),\(mid+1\le i<j \le R\):将 \([L,R]\) 拆为 \([L,mid],[mid+1,R]\),发现这两部分点对分别位于这两个区间中,递归处理这两部分。
  • \(L\le i\le mid,mid+1\le j\le R\):设法处理这些点对。

在实现上,通常设一个 solve(L,R) 函数来处理在 \([L,R]\) 区间内的点对:

void solve (int L, int R) {
	int mid = (L + R) >> 1; if (L == R) return ; // 边界 
	solve (L, mid); solve (mid + 1, R); // 递归处理更小的区间 
	... // 处理跨越 mid 的点对 
}

例题

三维偏序

solution

考虑使用 CDQ 分治。

将点按照 \(a_i\) 排序,对于一个区间 \([L,R]\),假设我们已经处理好了 \([L,mid],[mid+1,R]\) 内的点对,现在考虑处理跨越 \(mid\) 的点对。

对于点对 \((i,j)\)(\(i\le mid<j\)),因为我们已经按照 \(a_i\) 排序,所以 \(a_i\le a_j\) 就只要求 \(i\le j\),因为 \(i,j\) 分居 \(mid\) 两侧,所以这个限制显然满足。

我们把 \([L,mid],[mid+1,R]\) 区间内的点分别按照 \(b_i\) 排序。然后对于每一个 \(j\),考虑求出有多少 \(i\) 满足 \(b_i\le b_j\) 的限制条件。不难发现,在 \(j\) 逐渐向右移时,满足 \(b_i\le b_j\) 的 \(i\) 的区间右端点是不减的(区间左端点显然为 \(L\)),因此我们把 \(i,j\) 看作双指针,就可以线性维护。在 \(i\) 向右移动时,我们将经过的点的 \(c_i\) 插入树状数组,对于每一个 \(j\),只要查询有多少 \(c_i\le c_j\) 即可,这样就可以找到合法的点对。

时间复杂度 \(T(n)=2T(\left\lceil\frac n2\right\rceil)+\mathcal{O}(n\log n)=\mathcal{O}(n\log^2 n)\)

code

CI N = 1e5; struct node {int a; int b; int c;} p[N + 5], m[N + 5]; struct llsAKIOI {int b; int c; int id;} q[N + 5]; int n, K, BIT[N * 2 + 5], ans[N + 5], Tng[N + 5], dis[N + 5];
int lowbit (int x) {return x & -x;} void add (int id, int x) {for (; id <= K; id += lowbit (id)) BIT[id] += x;}
int query (int id) {int s = 0; for (; id; id -= lowbit (id)) s += BIT[id]; return s;}
bool cmp (node x, node y) {if (x.a != y.a) return x.a < y.a; if (x.b != y.b) return x.b < y.b; return x.c < y.c;} 
bool cmp2 (llsAKIOI x, llsAKIOI y) {return x.b == y.b ? x.c < y.c : x.b < y.b;}
void solve (int L, int R) {
	RI i, j; if (L == R) return ; int mid = (L + R) >> 1; solve (L, mid); solve (mid + 1, R); for (i = L; i <= R; ++ i) q[i].b = p[i].b, q[i].c = p[i].c, q[i].id = i;
	sort (q + L, q + mid + 1, cmp2); sort (q + mid + 1, q + R + 1, cmp2); i = L; for (j = mid + 1; j <= R; ++ j) {
		W (i <= mid && q[i].b <= q[j].b) add (q[i].c, dis[q[i].id]), ++ i; ans[q[j].id] += query (q[j].c);
	} W (i > L) -- i, add (q[i].c, - dis[q[i].id]);
}
int main () {
	RI i, j; for (Read (n, K), i = 1; i <= n; ++ i) Read (m[i].a, m[i].b, m[i].c); sort (m + 1, m + n + 1, cmp);
	int cnt = 0, tme = 0; for (i = 1; i <= n; ++ i) {
		++ tme; if (m[i].a != m[i + 1].a || m[i].b != m[i + 1].b || m[i].c != m[i + 1].c) {
			++ cnt; p[cnt] = m[i]; dis[cnt] = tme; tme = 0;
		}
	} solve (1, cnt);
	for (i = 1; i <= cnt; ++ i) Tng[ans[i] + dis[i] - 1] += dis[i]; for (i = 0; i < n; ++ i) printf ("%d\n", Tng[i]); printf ("\n");
	return 0; 
 }

[NOIP 2023 模拟赛五 By FXT B] 简单第三题

solution & code

NOIP 2023 模拟赛五 题解

标签:le,int,分治,mid,solve,CDQ,id
From: https://www.cnblogs.com/ClapEcho233/p/17544965.html

相关文章

  • cdq分治学习笔记
    做着做着cdq分治的题发现自己太菜了写不出来题XD,所以来写写学习笔记。CDQ分治CDQ分治一般有两个用途:解决偏序问题、将动态问题转化为静态问题。偏序问题我们先来介绍第一个问题:偏序问题。普通的二维偏序就类似于逆序对,每个元素有两个属性\(a_i,b_i\),我们需要统计\(a_......
  • 6307: 网线主管 二分/分治
    描述 仙境的居民们决定举办一场程序设计区域赛。裁判委员会完全由自愿组成,他们承诺要组织一次史上最公正的比赛。他们决定将选手的电脑用星形拓扑结构连接在一起,即将它们全部连到一个单一的中心服务器。为了组织这个完全公正的比赛,裁判委员会主席提出要将所有选手的电脑等距离......
  • 【树分治】HDOJ 5016
    先预处理出每个点的最近点。。。。然后考虑固定根,对于每个根,从根到子树的路径中任选两条,如果dis[i]+dis[j]<w[j]。那么i就是j的一个合法点。。。。然后递归处理子树即可。。。。扩栈才过的。。。#include<iostream>#include<queue>#include<stack>#include<map>#includ......
  • 线段树分治 学习笔记
    离线算法。在时间轴上建线段树(可能要事先离散化),要维护的东西用vector什么的挂在线段树的节点上,DFS一遍线段树,每次进入一个节点就加入要维护的东西,离开时撤销即可。由于DFS的特性,只需支持最近的undo,用stack可维护。......
  • CDQ分治 学习笔记
    按@ouuan大佬所说,CDQ分治可以当作ex归并看待。它的思想和归并排序十分相似:假设要对区间\([l,r)\)处理先不管\([\text{mid},r)\),计算\([l,mid)\)同理计算\([mid,r)\)补回之前忽略的部分,即“归并”例:三维偏序给定\(n\)个点\((a,b,c)\),求\(a_1\lea_2\we......
  • 分治专题
    在牛子老师的博客下边看到yspm给了CF1019E。看了一眼,不会。看了题解,我超边分治+闵可夫斯基和,一个都不会。乐。还有20天,还能补多少坑呢,不好说。仍然是每天高压作业。但是出乎意料的晚上不是很失眠,虽然说醒了以后还是很困。现象:让大象出现的事物或者方法。大象是一种体量......
  • 【杂题乱写】6 月多校分治专题训练
    AGym-101471DMoneyfornothing就是求\((d_j-c_i)(q_j-p_i)\)的最大值。可以看作点对\((d_j,q_j)\)与\((c_i,p_i)\)在二维平面上构成矩形的最大值,且\(c_i\ged_j,p_i\geq_j\)。把卖家点对放在序列\(a\),买家点对放在序列\(b\),先删去一定不优的点,删完之后\(a,b\)都......
  • 【杂题乱写】6 月多校分治专题训练
    AGym-101471DMoneyfornothing就是求\((d_j-c_i)(q_j-p_i)\)的最大值。可以看作点对\((d_j,q_j)\)与\((c_i,p_i)\)在二维平面上构成矩形的最大值,且\(c_i\ged_j,p_i\geq_j\)。把卖家点对放在序列\(a\),买家点对放在序列\(b\),先删去一定不优的点,删完之后\(a,b\)都......
  • 【杂题乱写】6 月多校分治专题训练
    AGym-101471DMoneyfornothing就是求\((d_j-c_i)(q_j-p_i)\)的最大值。可以看作点对\((d_j,q_j)\)与\((c_i,p_i)\)在二维平面上构成矩形的最大值,且\(c_i\ged_j,p_i\geq_j\)。把卖家点对放在序列\(a\),买家点对放在序列\(b\),先删去一定不优的点,删完之后\(a,b\)都......
  • 「学习笔记」CDQ分治
    CDQ分治的思想最早由IOI2008金牌得主陈丹琦在高中时整理并总结,目前这个思想的拓展十分广泛。优点:可以将数据结构或者DP优化掉一维缺点:这是离线算法。引入让我们来看一个问题有$n$个元素,第$i$个元素有$a_i,b_i,c_i$三个属性,设$f(i)$表示满足$a_j\l......