HNOI2016網路(整體二分+樹狀陣列)
題目大意
給定一棵樹,每次有三種事件。
1.設定一條路徑的權值為。
2.刪除某條設定。
3.詢問所有存在的設定中,不經過路徑的權值最大值是多少。
。
題解
剛開始只想到一個的樹剖做法……自己太菜了……
樹剖的話,考慮把一條路徑分成若干段重鏈,在dfs序上形成個連續區間,那麼它們之間的間隔區間也是的。
於是我們需要一個資料結構,支援區間插入值,區間刪除值,查詢區間最大值。於是樹套樹就行,或者線段樹每個節點維護一個雙堆,打標記下傳即可。複雜度。
整體二分真是又好寫複雜度又低的做法……
令二分的值為,考慮當前詢問是否使當前所有的路徑都經過它,如果是,那麼把它扔到左邊;否則扔到右邊。
具體的,我們可以用樹狀陣列維護一個樹上差分,就可以在的時間內解決了。
#include <bits/stdc++.h>
namespace IOStream {
const int MAXR = 10000000;
char _READ_[MAXR], _PRINT_[MAXR];
int _READ_POS_, _PRINT_POS_, _READ_LEN_;
inline char readc() {
#ifndef ONLINE_JUDGE
return getchar();
#endif
if (!_READ_POS_) _READ_LEN_ = fread(_READ_, 1, MAXR, stdin);
char c = _READ_[_READ_POS_++];
if (_READ_POS_ == MAXR) _READ_POS_ = 0;
if (_READ_POS_ > _READ_LEN_) return 0;
return c;
}
template<typename T> inline void read(T &x) {
x = 0; register int flag = 1, c;
while (((c = readc()) < '0' || c > '9') && c != '-');
if (c == '-') flag = -1; else x = c - '0';
while ((c = readc()) >= '0' && c <= '9') x = x * 10 - '0' + c;
x *= flag;
}
template<typename T1, typename ...T2> inline void read(T1 &a, T2&... x) {
read(a), read(x...);
}
inline int reads(char *s) {
register int len = 0, c;
while (isspace(c = readc()) || !c);
s[len++] = c;
while (!isspace(c = readc()) && c) s[len++] = c;
s[len] = 0;
return len;
}
inline void ioflush() { fwrite(_PRINT_, 1, _PRINT_POS_, stdout), _PRINT_POS_ = 0; fflush(stdout); }
inline void printc(char c) {
_PRINT_[_PRINT_POS_++] = c;
if (_PRINT_POS_ == MAXR) ioflush();
}
inline void prints(const char *s) {
for (int i = 0; s[i]; i++) printc(s[i]);
}
template<typename T> inline void print(T x, char c = '\n') {
if (x < 0) printc('-'), x = -x;
if (x) {
static char sta[20];
register int tp = 0;
for (; x; x /= 10) sta[tp++] = x % 10 + '0';
while (tp > 0) printc(sta[--tp]);
} else printc('0');
printc(c);
}
template<typename T1, typename ...T2> inline void print(T1 x, T2... y) {
print(x, ' '), print(y...);
}
}
using namespace IOStream;
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int MAXN = 200005;
struct Edge { int to, next; } edge[MAXN];
struct Option { int t, tp, u, v, x, l; } opt[MAXN], lo[MAXN], ro[MAXN];
struct Query { int t, x, id; } ask[MAXN], lq[MAXN], rq[MAXN];
int head[MAXN], beg[MAXN], ed[MAXN], st[20][MAXN], dep[MAXN];
int lg[MAXN], bit[MAXN], srt[MAXN], par[MAXN], res[MAXN], n, m, tot;
void addedge(int u, int v) {
edge[++tot] = (Edge) { v, head[u] };
head[u] = tot;
}
void dfs(int u, int fa) {
st[0][beg[u] = ++tot] = u;
par[u] = fa, dep[u] = dep[fa] + 1;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa) continue;
dfs(v, u);
st[0][++tot] = u;
}
ed[u] = tot;
}
void dfs2(int u, int fa) {
beg[u] = ++tot;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v != fa) dfs2(v, u);
}
ed[u] = tot;
}
int get_min(int x, int y) { return dep[x] < dep[y] ? x : y; }
int get_lca(int x, int y) {
x = beg[x], y = beg[y];
if (x > y) swap(x, y);
int l = lg[y - x + 1];
return get_min(st[l][x], st[l][y - (1 << l) + 1]);
}
void add(int x, int w) { x = beg[x]; for (; x <= n; x += x & -x) bit[x] += w; }
void clear(int x) { x = beg[x]; for (; x <= n; x += x & -x) bit[x] = 0; }
int sum(int x) { int res = 0; for (; x; x -= x & -x) res += bit[x]; return res; }
void divide(int l, int r, int ql, int qr, int cl, int cr) {
if (ql > qr) return;
if (l == r) {
for (int i = ql; i <= qr; i++) res[ask[i].id] = srt[l];
return;
}
int mid = (l + r) >> 1, clo = 0, cro = 0, clq = 0, crq = 0, now = 0;
for (int i = cl; i <= cr; i++) {
if (opt[i].x > srt[mid]) ro[++cro] = opt[i];
else lo[++clo] = opt[i];
}
if (cro == 0) divide(l, mid, ql, qr, cl, cr);
for (int i = 1, j = ql; i <= cro; i++) {
if (ro[i].tp == 0) {
++now;
add(ro[i].u, 1), add(ro[i].v, 1), add(ro[i].l, -1);
if (par[ro[i].l]) add(par[ro[i].l], -1);
} else {
--now;
add(ro[i].u, -1), add(ro[i].v, -1), add(ro[i].l, 1);
if (par[ro[i].l]) add(par[ro[i].l], 1);
}
for (; j <= qr && ask[j].t < ro[i].t; ++j) lq[++clq] = ask[j];
for (; j <= qr && (i == cro || ask[j].t < ro[i + 1].t); ++j) {
if (sum(ed[ask[j].x]) - sum(beg[ask[j].x] - 1) == now) lq[++clq] = ask[j];
else rq[++crq] = ask[j];
}
}
for (int i = 1; i <= clo; i++) opt[i + cl - 1] = lo[i];
for (int i = 1; i <= cro; i++) {
clear(ro[i].u), clear(ro[i].v), clear(ro[i].l);
if (par[ro[i].l]) clear(par[ro[i].l]);
opt[i + clo + cl - 1] = ro[i];
}
for (int i = 1; i <= clq; i++) ask[i + ql - 1] = lq[i];
for (int i = 1; i <= crq; i++) ask[i + clq + ql - 1] = rq[i];
divide(l, mid, ql, ql + clq - 1, cl, cl + clo - 1);
divide(mid + 1, r, ql + clq, qr, cl + clo, cr);
}
int main() {
read(n, m);
for (int i = 1; i < n; i++) {
int u, v; read(u, v);
addedge(u, v), addedge(v, u);
}
dfs(1, tot = 0);
for (int i = 1; i < 20; i++)
for (int j = 1; j + (1 << i) - 1 <= tot; j++)
st[i][j] = get_min(st[i - 1][j], st[i - 1][j + (1 << i >> 1)]);
for (int i = 2; i <= tot; i++) lg[i] = lg[i >> 1] + 1;
int cnt = 0, qc = 0, oc = 0;
for (int i = 1; i <= m; i++) {
int o; read(o);
if (o == 2) read(ask[++qc].x), ask[qc].t = i, ask[qc].id = qc;
else if (o == 0) {
++oc, read(opt[oc].u, opt[oc].v, opt[oc].x);
opt[oc].tp = 0, opt[oc].t = i, srt[++cnt] = opt[oc].x;
opt[oc].l = get_lca(opt[oc].u, opt[oc].v);
lo[i] = opt[oc];
} else {
++oc, read(opt[oc].x), opt[oc] = lo[opt[oc].x];
opt[oc].tp = 1, opt[oc].t = i;
}
}
dfs2(1, tot = 0);
srt[0] = -1;
sort(srt + 1, srt + 1 + cnt);
cnt = unique(srt + 1, srt + 1 + cnt) - srt - 1;
divide(0, cnt, 1, qc, 1, oc);
for (int i = 1; i <= qc; i++) print(res[i]);
ioflush();
return 0;
}
相關文章
- C105 整體二分+樹狀陣列 P2617 Dynamic Rankings陣列
- 樹狀陣列陣列
- HDU 6274 Master of Sequence(思維+樹狀陣列+二分)AST陣列
- 解析樹狀陣列陣列
- 樹狀陣列詳解陣列
- 樹狀陣列基礎陣列
- poj 2481 樹狀陣列陣列
- hdu 3874 樹狀陣列陣列
- 二維樹狀陣列陣列
- 樹狀陣列模板題 & (樹狀陣列 1:單點修改,區間查詢)陣列
- 樹狀陣列和逆序對陣列
- hdu 5147 樹狀陣列陣列
- 【筆記/模板】樹狀陣列筆記陣列
- 樹狀陣列快速入門陣列
- 樹狀陣列模板+習題集陣列
- 樹狀陣列3種基本操作陣列
- 學習筆記----樹狀陣列筆記陣列
- 樹狀陣列upc1976陣列
- CSU 4441 Necklace (樹狀陣列/LIS)陣列
- 樹狀陣列(我是真小白)陣列
- 資料結構——樹狀陣列資料結構陣列
- 線段樹+差分——【模板】樹狀陣列2陣列
- hdu 4836 The Query on the Tree(線段樹or樹狀陣列)陣列
- 10:Challenge 3(樹狀陣列直接修改)陣列
- POJ 3928 Ping pong(樹狀陣列)陣列
- HDU 1556 Color the ball(線段樹|樹狀陣列)陣列
- CF 293 E Close Vertices (樹的分治+樹狀陣列)陣列
- HDU 1166 敵兵佈陣 (樹狀陣列)陣列
- HDU 1166 敵兵佈陣(樹狀陣列)陣列
- C108 整體二分+樹狀陣列(區修+區查)P3332 [ZJOI2013] K大數查詢陣列
- AcWing 242. 一個簡單的整數問題(樹狀陣列解法)陣列
- 洛谷題單指南-二叉堆與樹狀陣列-P3368 【模板】樹狀陣列 2陣列
- POJ 2352(順路講解一下樹狀陣列)陣列
- POJ-2352 Stars(樹狀陣列)陣列
- 【luogu3368】模板 樹狀陣列 2陣列
- 【二維樹狀陣列】poj 2155 Matrix陣列
- D 區間求和 [數學 樹狀陣列]陣列
- 二維樹狀陣列-poj2155陣列