因为有$10^5$个宗教,需要开$10^5$个线段树。
平时开的线段树是“满”二叉树,但在这个题中代表一个宗教的线段树管辖的区间有很多点都不属于这个宗教,也就不用“把枝叶伸到这个点上”,所以这样用类似主席树的数组动态开点来建立$10^5$个只有几个“树枝”的线段树,维护轻重链就可以了
线段树的$L,R,l,r$弄反了调了好久$QAQ$ $so$ $sad$
#include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=getint() #define N 100003 using namespace std; inline int getint() {int k = 0, fh = 1; char c = getchar(); for(; c < ‘0‘ || c > ‘9‘; c = getchar()) if (c == ‘-‘) fh = -1; for(; c >= ‘0‘ && c <= ‘9‘; c = getchar()) k = k * 10 + c - ‘0‘; return k * fh;} struct Tree { int l, r, ma, sm; } T[4000010]; struct G { int nxt, to; } E[N << 1]; int root[N], point[N], cnt = 0, n, q, W[N], C[N], sz[N], son[N], up[N]; int deep[N], fa[N], watch[N]; inline void ins(int x, int y) {E[++cnt].nxt = point[x]; E[cnt].to = y; point[x] = cnt;} inline void _(int x) { sz[x] = 1; for(int tmp = point[x]; tmp; tmp = E[tmp].nxt) { int v = E[tmp].to; if (v == fa[x]) continue; fa[v] = x; deep[v] = deep[x] + 1; _(v); if (sz[v] > sz[son[x]]) son[x] = v; sz[x] += sz[v]; } } inline void __(int x) { watch[x] = ++cnt; if (!son[x]) return; up[son[x]] = up[x]; __(son[x]); for(int tmp =point[x]; tmp; tmp = E[tmp].nxt) { int v = E[tmp].to; if (v == fa[x] || v == son[x]) continue; up[v] = v; __(v); } } inline void pushup(int pos) { T[pos].sm = T[T[pos].l].sm + T[T[pos].r].sm; T[pos].ma = max(T[T[pos].l].ma, T[T[pos].r].ma); } inline void update(int &pos, int l, int r, int to, int num) { if (pos == 0) pos = ++cnt; if (l == r) {T[pos].ma = T[pos].sm = num; return;} int mid = (l + r) >> 1; if (to <= mid) update(T[pos].l, l, mid, to, num); else update(T[pos].r, mid + 1, r, to, num); pushup(pos); } inline int Qsum(int pos, int L, int R, int l, int r) { if (L <= l && r <= R) return T[pos].sm; int mid = (l + r) >> 1, s = 0; if (L <= mid) s += Qsum(T[pos].l, L, R, l, mid); if (R > mid) s += Qsum(T[pos].r, L, R, mid + 1, r); return s; } inline int Qmax(int pos, int L, int R, int l, int r) { if (L <= l && r <= R) return T[pos].ma; int mid = (l + r) >> 1, s = 0; if (L <= mid) s = Qmax(T[pos].l, L, R, l, mid); if (R > mid) s = max(s, Qmax(T[pos].r, L, R, mid + 1, r)); return s; } inline int Max(int CC, int x, int y) { int ans = 0; while (up[x] != up[y]) { if (deep[up[x]] < deep[up[y]]) swap(x, y); ans = max(ans, Qmax(root[CC], watch[up[x]], watch[x], 1, n)); x = fa[up[x]]; } if (deep[x] > deep[y]) swap(x, y); ans = max(ans, Qmax(root[CC], watch[x], watch[y], 1, n)); return ans; } inline int Sum(int CC, int x, int y) { int ans = 0; while (up[x] != up[y]) { if (deep[up[x]] < deep[up[y]]) swap(x, y); ans += Qsum(root[CC], watch[up[x]], watch[x], 1, n); x = fa[up[x]]; } if (deep[x] > deep[y]) swap(x, y); ans += Qsum(root[CC], watch[x], watch[y], 1, n); return ans; } int main() { read(n); read(q); for(int i = 1; i <= n; ++i) read(W[i]), read(C[i]); int u, v; for(int i = 1; i < n; ++i) { read(u); read(v); ins(u, v); ins(v, u); } _(1); up[1] = 1; cnt = 0; __(1); cnt = 0; for(int i = 1; i <= n; ++i) update(root[C[i]], 1, n, watch[i], W[i]); char c; int x, y; for(int i = 1; i <= q; ++i) { for(c = getchar(); c < ‘A‘ || c > ‘Z‘; c = getchar()); if (c == ‘C‘) { c = getchar(); read(x); read(y); if (c == ‘C‘) { update(root[C[x]], 1, n, watch[x], 0); C[x] = y; update(root[C[x]], 1, n, watch[x], W[x]); } else { update(root[C[x]], 1, n, watch[x], y); W[x] = y; } } else { c = getchar(); read(x); read(y); if (c == ‘S‘) printf("%d\n", Sum(C[x], x, y)); else printf("%d\n", Max(C[x], x, y)); } } return 0; }
hhhhhhhhhhhhhhhhhh调出来真的不容易啊,树链剖分怎么比$LCT$都难写!!!
$Try$ $Everything$
$演唱:Shakira$
Oh oh oh oh oooh
噢 噢 噢 噢
Oh oh oh oh oooh
噢 噢 噢 噢
Oh oh oh oh oooh
噢 噢 噢 噢
Oh oh oh oh oooh
噢 噢 噢 噢
I messed up tonight I lost another fight
刚搞砸了这一头 却又没顾得上那一头
I still mess up but I‘ll just start again
反复犯错却仍想重新来过
I keep falling down I keep on hitting the ground
不断跌倒 不断失败 也要不断重来
I always get up now to see what‘s next
想要触碰未来的心总会让我再站起来 继续大步前迈
Birds don‘t just fly they fall down and get up
在天空飞翔的鸟儿也难免会受伤会折翼 但也会重新振翅飞起
Nobody learns without getting it won
想要靠近蓝天就得有不怕坠落不怕受伤的勇气
I won‘t give up no I won‘t give in
我不会轻言放弃 谁也别想能让我放弃
Till I reach the end and then I‘ll start again
不停向前直到我达成心愿 然后又向更高的天空迈进
No I won‘t leave I wanna try everything
我不会逃避也不会迟疑 愿去尝试生命不同的绮丽
I wanna try even though I could fail
即使前路崎岖 未来阴晴不定 但至少我能体会到风雨过后的别样风景
I won‘t give up no I won‘t give in
我不会轻言放弃 谁也别想能让我放弃
Till I reach the end and then I‘ll start again
不停向前直到我达成心愿 然后又向更高的天空迈进
No I won‘t leave I wanna try everything
我不会逃避也不会迟疑 愿去尝试生命不同的绮丽
I wanna try even though I could fail
即使前路崎岖 未来阴晴不定 但至少我能体会到风雨过后的别样风景
Oh oh oh oh oooh
噢 噢 噢 噢
Try everything
去尝试生命不同的绮丽
Oh oh oh oh oooh
噢 噢 噢 噢
Try everything
去体验风雨过后的别样风景
Oh oh oh oh oooh
噢 噢 噢 噢
Try everything
让勇于尝试的勇气写就生命别样的意义
Oh oh oh oh oooh
噢 噢 噢 噢
Look at how far you‘ve come you filled your heart with love
当你想放弃 就回头看看你走过了多少崎岖 心中的那些爱又成就了一个怎样的你
Baby you‘ve done enough that cut your breath
别泄气 你已经做得够好了
Don‘t beat yourself up don‘t need to run so fast
别自暴自弃 也别太过心急
Sometimes we come last but we did our best
成功或许会迟些才降临 但尽过全力至少不会遗憾唏嘘
I won‘t give up no I won‘t give in
我不会轻言放弃 谁也别想能让我放弃
Till I reach the end and then I‘ll start again
不停向前直到我达成心愿 然后又向更高的天空迈进
No I won‘t leave I wanna try everything
我不会逃避也不会迟疑 愿去尝试生命不同的绮丽
I wanna try even though I could fail
即使前路崎岖 未来阴晴不定 但至少我能体会到风雨过后的别样风景
I won‘t give up no I won‘t give in
我不会轻言放弃 谁也别想能让我放弃
Till I reach the end and then I‘ll start again
不停向前直到我达成心愿 然后又向更高的天空迈进
No I won‘t leave I wanna try everything
我不会逃避也不会迟疑 愿去尝试生命不同的绮丽
I wanna try even though I could fail
即使前路崎岖 未来阴晴不定 但至少我能体会到风雨过后的别样风景
I‘ll keep on making those new mistakes
我会继续勇敢去体验 即使我还会不停犯错
I‘ll keep on making them every day
不断尝试不断犯错
Those new mistakes
不断犯错不断重新来过
Oh oh oh oh oooh
噢 噢 噢 噢
Try everything
不断尝试不断重新来过
Oh oh oh oh oooh
噢 噢 噢 噢
Try everything
不断体验生命中的不同结果
Oh oh oh oh oooh
噢 噢 噢 噢
Try everything
不断体验不断迈向更好的自我
Oh oh oh oh oooh
噢 噢 噢 噢
Try everything
让勇于尝试的勇气写就生命的别样意义