CDQ 分治
模板¶
按照值域進行分治,並非 index
非嚴格¶
洛谷 P3810 三维偏序
給 \(n\) 個三維空間的點 \((x,y,z)\),問對於第 \(i\) 個點,有幾個 \(j\) 滿足 \(x_j\ge x_i,y_j\ge y_i,z_j\ge z_i\)
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
|
嚴格¶
Zerojudge c571.三維偏序
給 \(n\) 個三維空間的點 \((x,y,z)\),問對於第 \(i\) 個點,有幾個 \(j\) 滿足 \(x_j>x_i,y_j>y_i,z_j>z_i\)
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
|
例題¶
矩形加矩形求和¶
CSES Forest Queries II
在二維平面上,支持以下操作
-
支持在一個矩形區域內加一個數字
-
每次詢問一個矩形區域的和
思路
「詢問一個矩形區域的和」可以看做是四個詢問 \((x_i,y_i)\) 的數值總和
那要怎麼維護操作先後順序呢 ? 我們可以多加一為 \(z\) 表示此操作的時間戳記,問題就變成
給定一個 \((x_i,y_i,z_i)\) 詢問 \(\begin{cases}x_j \le x_i \\ y_j \le y_i \\ z_j \le z_i \end{cases}\) 的權值總和
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
|
- 類似題 : APIO 2019 路燈
NPSC 忙碌的國度¶
NPSC 2019 高中組 pB. 忙碌的國度
有 \(n\) 間公司和 \(m\) 間餐廳,每個員工有位置 \((x_i,y_i)\) 和下班時間 \(t_i\),每間餐廳有位置 \((p_i,q_i)\),關閉時間 \(c_i\) 和美味程度 \(v_i\)
第 \(i\) 個人可以吃到第 \(j\) 個餐廳必須滿足
問對每個員工能吃到的餐廳(最多一間)的最大美味程度
思路
假設 \(\begin{cases} p_j \le x_i \\ q_j \le y_i \end{cases}\) 那我們可將式子拆成
兩點即變成 \((x,y,z)=\begin{cases}(x_i, \space y_i,\space t_i + x_i + y_i) \\ (p_j,\space q_j,\space p_j + q_j + c_j) \end{cases}\)
問題就變成給 \((x_i,y_i,z_i)\) 問
另外 3 種大小關西也同理
全國賽 百萬刮刮樂¶
2022 全國賽 pF. 百萬刮刮樂
給定 \((a_i,b_i,c_i)\) 與 \(w_i\) 問對於所有相異且符合以下條件的 \(i,j\), \(w_i+w_j\) 可能是多少
思路
法 1 : CDQ 分治
所以對於符合 \(\begin{cases}x_j\le -x_i \\ y_j \le -y_i \\ z_j \le -z_i \end{cases}\) 的這些 \(j\) 我們可以去看
記得要特判 \(w_i=w_j\) 的 case,可以預先在 ans[i] 裡消除其貢獻
時間複雜度 : \(O(n\log^2 n)\)
法 2 : 線段樹維護
另一種方法也差不多,我們先分別枚舉好 \(w_i,w_j\) 的值
問題就變成找對於每個 \(i\) 有沒有 \(j\) 符合 \(\begin{cases}x_j\le -x_i \\ y_j \le -y_i \\ z_j \le -z_i \end{cases}\) 的就好
所以我們可以直接將用掃描線從左到右掃,然後對於 \((-x_i,-y_i,-z_i)\) 要去
就是看之前 \(y_j \le -y_i\) 的最小 \(z_j\) 有幾個
\(w_i=w_j\) 時也需預先扣掉自己的貢獻
時間複雜度 : \(O(n\log n)\)
法 3 : BIT
將這些 tuple 以 \(w_i\) 分成 \(S_1,S_2,S_3\) 三組,並在每組裡面依照 \(a_i\) 小到大 sort。
對於兩組 \(S_p\) 與 \(S_q\) 做以下的事情 :
-
令 \(T=w_p+w_q\)
-
開一個 data structure D
-
for each \((a,b,c)\) in \(S_p\) :
- 將 \(S_q\) 裡面符合 \(x+a\ge T\) 的 tuple 的 \((y,z)\) insert 進去 D(具有單調性)
- 如果 D 裡面有 pair 符合 \((\ge T - b, \ge T - c)\) 那就 return true
-
其中 D 可以用值域 BIT 維護,index 維護 pair 的 \(x\),value 維護 pair 的 \(y\),每次要去 query 的時候只要查詢一個後綴的最大值即可!
TIOJ 2030¶
TIOJ 2030.盩僰麌過街 人人喊打
給你長度為 \(N\) 的序列 \(a_1\sim a_N\),請支援 \(Q\) 次以下操作 :
-
\(1\space p\space v:\) 把 \(a_p\) 改成 \(v\)
-
\(2\space L\space R\space V:\) 設置一道雷射光在 \([L,R]\),強度為 \(V\),保證之前沒有左界在 \(L\) 的雷射光
-
\(3\space L:\) 移除左界在 \(L\) 的雷射光,保證之前有一個左界在 \(L\) 的雷射光
-
\(4\space L\space R:\) 計算 \([L,R]\) 之間的不重複數字,以及 \([L,R]\) 之間所有被完全覆蓋在內的雷射光強度總和
\(N,Q\le 10^5\)
思路
\((L_j,R_j,t_j)\)
更改想成兩個步驟,消除 \(a_p\) 的貢獻,加入 \(v\) 的貢獻
\(-a_p\) :
存 \((idx,nxt,t_i),-1:\)
index, 在之前 \(a_p\) 出現的那個時刻下一次出現的位置, 現在的時間戳記
改成 \(v:\)
存 \((idx,nxt,t_i),+1:\)
index, 在現在 \(v\) 下一次出現的位置, 現在的時間戳記
\(+(L_i, R_i, t_i),+V:\) 加入的時刻
\(-(L_i, R_i, t_i),-V:\) 加入的時刻
洛谷 动态逆序对¶
洛谷 P3157 [CQOI2011]动态逆序对
現在給出 \(1\sim n\) 的一個排列,按照某種順序依次刪除 \(m\) 個元素
在每次刪除一個元素之前統計整個序列的逆序數對的個數
\(n\le 10^5,m\le 5\times 10^4\)
思路
對於初始的陣列,我們的 tuple 就是 \((i,a_i,t_i=1),+1\)
然後先算好逆序數對個數
再來對每一次的刪除,我們先 query\((i,a_i,t_i)\),然後加入 tuple \((i,a_i,t_i),-1\)
對於每個 query \((i,a_i,t_i)\) 我要算那些 \(j\) 滿足 \(\begin{cases}i<j\\ a_i > a_j \\ t_i \ge t_j\end{cases}\)
CF 1093E¶
CF 1093 E.Intersection of Permutations
給你兩個陣列 \(a,b\),兩個陣列都恰好包含 \(1 \sim n\) 的每個數字
接下來有 m 次操作:
-
詢問 \(1 \sim n\) 有多少種數字同時出現在 \(a\) 陣列的區間 \([l_a, r_a]\) 和 \(b\) 陣列的區間 \([l_b, r_b]\)
-
交換 \(b_x\) 和 \(b_y\)
\(1 \le n, m \le 2 \times 10^5\)