建國中學 賴昭勳
懶標分成兩種:
\(seg[cur]\)代表當前節點經過子節點修改後的答案
該節點的懶標對\(seg[cur]\)做事,遇到的時候再處理。
這份講義會討論第二種
\(n, q \leq 2 * 10^5\)
假設這兩個地方都有標記...
5
8
標記的先後會互相影響!
5
5
5
5, 5, 5, 5, 5...
X
4
\(seg[cur]\)紀錄的是「左右子節點更新完答案之後的結果」
合併時考慮左右節點與他們的懶標
2, 1, 4, 7
4, 4, 4, 4
相加
#include <iostream>
#include <algorithm>
#define maxn 100005
using namespace std;
int seg[4 * maxn], lazy[4 * maxn];
void modify(....) {
if (r <= l || ql >= r || qr <= l) return;
if (ql <= l && qr >= r) {
PUT_TAG;
return;
}
int mid = (l + r) / 2;
modify(LEFT_CHILD);
modify(RIGHT_CHILD);
PULL seg[cur];
}
應該在哪裡加上push操作?
PUSH(cur);
PUSH(LEFT);
PUSH(RIGHT);
#include <iostream>
#include <algorithm>
#define maxn 100005
using namespace std;
int seg[4 * maxn], lazy[4 * maxn];
void modify(....) {
if (r <= l || ql >= r || qr <= l) return;
if (ql <= l && qr >= r) {
PUT_TAG;
return;
}
int mid = (l + r) / 2;
modify(LEFT_CHILD);
modify(RIGHT_CHILD);
PULL seg[cur];
}
應該在哪裡加上push操作?
PUSH(cur);
PUSH(LEFT);
PUSH(RIGHT);
int query(....) {
if (r <= l || ql >= r || qr <= l) return 0;
if (ql <= l && qr >= r) {
return seg[cur];
}
int mid = (l + r) / 2;
return COMBINE(query(LEFT) + query(RIGHT));
}
push(cur);
應該在哪裡加上push操作?
int query(....) {
if (r <= l || ql >= r || qr <= l) return 0;
if (ql <= l && qr >= r) {
return seg[cur];
}
int mid = (l + r) / 2;
return COMBINE(query(LEFT) + query(RIGHT));
}
push(cur);
應該在哪裡加上push操作?
修改,詢問皆為\(O(logn)\)
void push(int cur, int l, int r) { //[l, r)
seg[cur] = (r - l) * tag[cur];
if (r - l > 1) {
tag[cur * 2] = tag[cur];
tag[cur * 2 + 1] = tag[cur];
}
tag[cur] = 0;
}
但是在push裡面要怎麼寫...
如果在同一個區間,我之前有加值的標記,現在新增一個改值操作,那改值操作會把加值覆蓋掉
因此,實作的時候要保證:如果一個節點同時有加值和改值標記,那一定代表是先改值後加值。
寫push 的時候:
給你一個正整數序列\(A\),支援兩種操作
1. 把區間\([l, r]\)的數字\(a_i\)全部改成\(min(a_i, x)\)
2. 把區間\([l, r]\)的數字\(a_i\)全部改成\(max(a_i, x)\)
最後請輸出整個序列
\(n \leq 2 \times 10^6, q \leq 5 \times 10^5\)
1. 單點修改某個元素的值
2. 詢問區間\([l, r]\)的最大連續和
有三種可能:
對於每個區間,我們需要知道:
答案會是:\(\max(left.all, right.all, left.suf + right.pref)\)
1. 把\([l, r]\)的值加上\(k\)
2. 詢問區間\([l, r]\)的最大公因數
\(n, q \leq 10^5\)
1. 把\(a_i\)加上\(k\)
2. 詢問整個序列,選取任意多個互不相鄰元素的最大和
\(n \leq 40000, \ q \leq 50000\)
給你一個序列,支援兩種操作:
1. 單點改值
2. 詢問總和\(\leq x\)的最長前綴長度(aka對前綴取lower_bound)
\(n, q \leq 5 \times 10^5, a_i \geq 0\)
總複雜度:\(O(n + qlog^2n)\)
可不可以更好?
Query: 30
Sum: 13
Query: 17
Sum: 20
\(n \leq 8 \times 10^5\)
大致想法:把資料的兩個維度畫在空間平面上。枚舉一個維度,並用線段樹解決掉另一個維度。
不管是原本的資料,修改,或是詢問都可以對應到空間上的點、線、或平面!
也就是說,往往是離線處理詢問
給你一個兩個1~n的排列\(a, b\),有\(q\)筆詢問。每次詢問\(a[l_1...r_1]\)和\(b[l_2...r_2]\)的組成元素是否相同
\(n, q \leq 10^5\)
給你一個序列,支援兩種操作:
1. 單點改值
2. 給你一個\(x\),詢問\(max(a_i \oplus x)\)
\(n, q \leq 2 \times 10^5, 0 \leq a_i \leq 10^9\)
祝各位魔境加油 ;P