其实一个合理的引入对学生的兴趣影响很大
− c q b z g m \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad -cqbzgm −cqbzgm
但是竞赛哪里有那么多兴趣 , 更重要的是恒心与毅 力 ( 虽然我没有 但是竞赛哪里有那么多兴趣,更重要的是恒心与毅力_{~~(虽然我没有~~} 但是竞赛哪里有那么多兴趣,更重要的是恒心与毅力 (虽然我没有
树链剖分,顾名思义,指一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链,保证每个点属于且只属于一条链,然后再通过数据结构(树状数组、BST、SPLAY、线段树等)来维护每一条链。
− 源于百度百科 \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad -源于百度百科 −源于百度百科
光写个概念是无用的,我们还得去想办法实现.
我们先引入一点东西:
重儿子:一个结点的所有儿子中,子树节点数最多的那个
轻儿子:一个结点除重儿子以外的其他儿子
重链:从一个轻儿子开始,一直往他的重儿子走出的链
轻链:除重链外的其他链
然后看这张图:
再按照优先遍历重链对结点重新编号:
然后你就会发现,我们完成了 d f s dfs dfs序.
根据以上的流程,我们就可以写 d f s dfs dfs序了.
代码:
/*
dfs1:找出所有结点之间的关系 并求得每个结点的重儿子
dfs2:对所有结点重新编号
id[u]:dfs序后的编号
tmp[cnt]:序号cnt对应结点u
fa[u]:u的父亲结点
d[u]:u的深度
size[u]:u为根节点的子树的结点个数
son[u]:u的重儿子
top[u]:u所在的重链顶端结点
*/
void dfs1(int u){
size[u] = 1, d[u] = d[fa[u]] + 1;//这个点本身size=1,深度为他父亲+1
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v == fa[u])continue;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[son[u]] < size[v])son[u] = v;//求重儿子
}
}
void dfs2(int u, int front){
top[u] = front, id[u] = ++ cnt, tmp[cnt] = u;
if(son[u])dfs2(son[u], front);
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v != fa[u] && v != son[u])dfs2(v, v);//一个点位于轻链底端,那么他的top必然是它本身
}
}
然后我们就可以迎接例题了~~(终于写完了 h h h _{hhh} hhh~~
P 3384 P3384 P3384
1 x y z,表示将树从 x x x 到 y y y 结点最短路径上所有节点的值都加上 z z z。
2 x y,表示求树从 x x x 到 y y y 结点最短路径上所有节点的值之和。
3 x z,表示将以 x x x 为根节点的子树内所有节点值都加上 z z z。
4 x 表示求以 x x x 为根节点的子树内所有节点值之和
#include
using namespace std;
const int MAXN = 1e5 + 5;
#define lson Tree[x].ls
#define rson Tree[x].rs
#define lz Tree[x].lazy
#define len(x) (Tree[x].r - Tree[x].l + 1)
struct edge{
int next, to;
}g[MAXN << 1];
struct Segment_Tree{
int l, r, ls, rs, sum, lazy;
}Tree[MAXN << 2];
int head[MAXN << 1], cnt;
int n, m, r, mod, a[MAXN], root;
int fa[MAXN], d[MAXN], son[MAXN], size[MAXN], top[MAXN], id[MAXN], tmp[MAXN];
void add(int u, int v){
g[++ cnt] = (edge){head[u], v};
head[u] = cnt;
}
void dfs1(int u){
size[u] = 1, d[u] = d[fa[u]] + 1;
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v == fa[u])continue;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[son[u]] < size[v])son[u] = v;
}
}
void dfs2(int u, int front){
top[u] = front, id[u] = ++ cnt, tmp[cnt] = u;
if(son[u])dfs2(son[u], front);
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v != fa[u] && v != son[u])dfs2(v, v);
}
}
void pushup(int x){
Tree[x].sum = (Tree[lson].sum + Tree[rson].sum) % mod;
}
void pushdown(int x){
if(!lz)return ;
Tree[lson].lazy += lz, Tree[lson].lazy %= mod;
Tree[rson].lazy += lz, Tree[rson].lazy %= mod;
Tree[lson].sum += lz * len(lson), Tree[lson].sum %= mod;
Tree[rson].sum += lz * len(rson), Tree[rson].sum %= mod;
lz = 0;
}
void build(int l, int r, int x){
Tree[x].l = l, Tree[x].r = r;
if(l == r){
Tree[x].sum = a[tmp[l]];
return ;
}
int mid = l + r >> 1;
lson = cnt ++, rson = cnt ++;
build(l, mid, lson), build(mid + 1, r, rson);
Tree[x].l = Tree[lson].l, Tree[x].r = Tree[rson].r;
pushup(x);
}
void update(int l, int r, int k, int x){
if(Tree[x].l >= l && Tree[x].r <= r){
lz += k, lz %= mod;
Tree[x].sum += len(x) * k, Tree[x].sum %= mod;
return ;
}
pushdown(x);
int mid = Tree[x].l + Tree[x].r >> 1;
if(mid >= l)update(l, r, k, lson);
if(mid < r)update(l, r, k, rson);
pushup(x);
}
int query(int l, int r, int x){
if(Tree[x].l >= l && Tree[x].r <= r)return Tree[x].sum;
pushdown(x);
int mid = Tree[x].l + Tree[x].r >> 1, sum = 0;
if(mid >= l)sum += query(l, r, lson);
if(mid < r)sum += query(l, r, rson);
return sum % mod;
}
int sum(int l, int r){
int res = 0;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res += query(id[top[l]], id[l], root), res %= mod;
l = fa[top[l]];
}
if(id[l] > id[r])swap(l, r);
return (res + query(id[l], id[r], root)) % mod;
}
void updates(int l, int r, int x){
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
update(id[top[l]], id[l], x, root);
l = fa[top[l]];
}
if(id[l] > id[r])swap(l, r);
update(id[l], id[r], x, root);
}
int main(){
scanf("%d %d %d %d", &n, &m, &r, &mod);
for(int i = 1; i <= n; i ++)scanf("%d", &a[i]);
for(int i = 1; i < n; i ++){
int u, v;
scanf("%d %d", &u, &v);
add(u, v), add(v, u);
}
cnt = 0, dfs1(r), dfs2(r, r);
cnt = 0, build(1, n, root = cnt ++);
for(int i = 1; i <= m; i ++){
int opt, x, y, k;
scanf("%d", &opt);
if(opt == 1){
scanf("%d %d %d", &x, &y, &k);
updates(x, y, k);
}
else if(opt == 2){
scanf("%d %d", &x, &y);
printf("%d\n", sum(x, y));
}
else if(opt == 3){
scanf("%d %d", &x, &y);
update(id[x], id[x] + size[x] - 1, y, root);
}
else {
scanf("%d", &x);
printf("%d\n", query(id[x], id[x] + size[x] - 1, root));
}
}
return 0;
}
P 2590 P2590 P2590:
I. CHANGE u t : 把结点 u u u 的权值改为 t t t。
II. QMAX u v: 询问从点 u u u 到点 v v v 的路径上的节点的最大权值。
III. QSUM u v: 询问从点 u u u 到点 v v v 的路径上的节点的权值和。
#include
using namespace std;
const int MAXN = 1e5 + 5;
#define lson pos << 1
#define rson pos << 1 | 1
struct edge{
int next, to;
}g[MAXN << 1];
struct Segment_Tree{
int l, r, sum, maxn;
Segment_Tree(){
l = r = sum = 0;
maxn = -0x3f3f3f3f;
}
}Tree[MAXN << 2];
int head[MAXN << 1], cnt;
int n, m, r, mod, a[MAXN];
int fa[MAXN], d[MAXN], son[MAXN], size[MAXN], top[MAXN], id[MAXN], tmp[MAXN], tot;
void add(int u, int v){
g[++ cnt] = (edge){head[u], v};
head[u] = cnt;
}
void dfs1(int u){
size[u] = 1;
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v == fa[u])continue;
d[v] = d[u] + 1;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[son[u]] < size[v])son[u] = v;
}
}
void dfs2(int u, int front){
top[u] = front, id[u] = ++ tot, tmp[tot] = u;
if(son[u])dfs2(son[u], front);
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v != fa[u] && v != son[u])dfs2(v, v);
}
}
void pushup(int pos){
Tree[pos].sum = Tree[lson].sum + Tree[rson].sum;
Tree[pos].maxn = max(Tree[lson].maxn, Tree[rson].maxn);
}
void build(int pos, int l, int r){
Tree[pos].l = l, Tree[pos].r = r;
if(l == r){
Tree[pos].sum = Tree[pos].maxn = a[tmp[l]];
return ;
}
int mid = l + r >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
pushup(pos);
}
void update(int pos, int k, int x){
if(Tree[pos].l == Tree[pos].r){
Tree[pos].sum = Tree[pos].maxn = x;
return ;
}
int mid = Tree[pos].l + Tree[pos].r >> 1;
if(k <= mid)update(lson, k, x);
else update(rson, k, x);
pushup(pos);
}
int querymax(int pos, int ql, int qr){
if(ql <= Tree[pos].l && Tree[pos].r <= qr)return Tree[pos].maxn;
int mid = Tree[pos].l + Tree[pos].r >> 1, maxn = -0x3f3f3f3f;
if(ql <= mid)maxn = max(maxn, querymax(lson, ql, qr));
if(qr > mid) maxn = max(maxn, querymax(rson, ql, qr));
return maxn;
}
int querysum(int pos, int l, int r, int ql, int qr){
if(ql <= l && r <= qr)return Tree[pos].sum;
int mid = l + r >> 1, sum = 0;
if(ql <= mid)sum += querysum(lson, l, mid, ql, qr);
if(qr > mid)sum += querysum(rson, mid + 1, r, ql, qr);
return sum;
}
int getmax(int l, int r){
int res = -0x3f3f3f3f;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res = max(res, querymax(1, id[top[l]], id[l]));
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
return max(res, querymax(1, id[l], id[r]));
}
int getsum(int l, int r){
int res = 0;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res += querysum(1, 1, n, id[top[l]], id[l]);
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
return res + querysum(1, 1, n, id[l], id[r]);
}
int main(){
scanf("%d", &n);
for(int i = 1; i < n; i ++){
int u, v;
scanf("%d %d", &u, &v);
add(u, v), add(v, u);
}
for(int i = 1; i <= n; i ++)scanf("%d", &a[i]);
scanf("%d", &m);
fa[1] = d[1] = 1;
dfs1(1), dfs2(1, 1);
build(1, 1, n);
for(int i = 1; i <= m; i ++){
string opt;
int x, y;
cin >> opt;
if(opt == "CHANGE"){
scanf("%d %d", &x, &y);
update(1, id[x], y);
}
else if(opt == "QMAX"){
scanf("%d %d", &x, &y);
printf("%d\n", getmax(x, y));
}
else{
scanf("%d %d", &x, &y);
printf("%d\n", getsum(x, y));
}
}
return 0;
}
P3178
操作 1 1 1 :把某个节点 x x x 的点权增加 a a a 。
操作 2 2 2 :把某个节点 x x x 为根的子树中所有点的点权都增加 a 。
操作 3 3 3 :询问某个节点 x x x 到根的路径中所有点的点权和。
#include
using namespace std;
const int MAXN = 1e5 + 5;
#define lson pos << 1
#define rson pos << 1 | 1
#define len(x) (Tree[x].r - Tree[x].l + 1)
#define lz Tree[pos].lazy
#define int long long
struct edge{
int next, to;
}g[MAXN << 1];
struct Segment_Tree{
int l, r, ls, rs, sum, lazy;
Segment_Tree(){
l = r = sum = 0;
}
}Tree[MAXN << 2];
int head[MAXN << 1], cnt;
int n, m, r, mod, a[MAXN];
int fa[MAXN], d[MAXN], son[MAXN], size[MAXN], top[MAXN], id[MAXN], tmp[MAXN], tot;
void add(int u, int v){
g[++ cnt] = (edge){head[u], v};
head[u] = cnt;
}
void dfs1(int u){
size[u] = 1;
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v == fa[u])continue;
d[v] = d[u] + 1;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[son[u]] < size[v])son[u] = v;
}
}
void dfs2(int u, int front){
top[u] = front, id[u] = ++ tot, tmp[tot] = u;
if(son[u])dfs2(son[u], front);
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v != fa[u] && v != son[u])dfs2(v, v);
}
}
void pushdown(int pos){
if(!lz)return ;
Tree[lson].lazy += lz;
Tree[rson].lazy += lz;
Tree[lson].sum += lz * len(lson);
Tree[rson].sum += lz * len(rson);
lz = 0;
}
void build(int pos, int l, int r){
Tree[pos].l = l, Tree[pos].r = r;
if(l == r){
Tree[pos].sum = a[tmp[l]];
return ;
}
int mid = l + r >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
Tree[pos].sum = Tree[lson].sum + Tree[rson].sum;
}
void update(int pos, int k, int x){
if(Tree[pos].l == Tree[pos].r){
Tree[pos].sum += x;
return ;
}
pushdown(pos);
int mid = Tree[pos].l + Tree[pos].r >> 1;
if(k <= mid)update(lson, k, x);
else update(rson, k, x);
Tree[pos].sum = Tree[lson].sum + Tree[rson].sum;
}
void update1(int l, int r, int k, int pos){
if(Tree[pos].l >= l && Tree[pos].r <= r){
lz += k;
Tree[pos].sum += len(pos) * k;
return ;
}
pushdown(pos);
int mid = Tree[pos].l + Tree[pos].r >> 1;
if(mid >= l)update1(l, r, k, lson);
if(mid < r)update1(l, r, k, rson);
Tree[pos].sum = Tree[lson].sum + Tree[rson].sum;
}
int querysum(int pos, int l, int r, int ql, int qr){
if(ql <= l && r <= qr)return Tree[pos].sum;
int mid = l + r >> 1, sum = 0;
pushdown(pos);
if(ql <= mid)sum += querysum(lson, l, mid, ql, qr);
if(qr > mid)sum += querysum(rson, mid + 1, r, ql, qr);
return sum;
}
int getsum(int l, int r){
int res = 0;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res += querysum(1, 1, n, id[top[l]], id[l]);
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
return res + querysum(1, 1, n, id[l], id[r]);
}
signed main(){
scanf("%lld %lld", &n, &m);
for(int i = 1; i <= n; i ++)scanf("%lld", &a[i]);
for(int i = 1; i < n; i ++){
int u, v;
scanf("%lld %lld", &u, &v);
add(u, v), add(v, u);
}
fa[1] = d[1] = 1;
dfs1(1), dfs2(1, 1);
build(1, 1, n);
for(int i = 1; i <= m; i ++){
int opt, x, y;
scanf("%lld", &opt);
if(opt == 1){
scanf("%lld %lld", &x, &y);
update(1, id[x], y);
}
else if(opt == 2){
scanf("%lld %lld", &x, &y);
update1(id[x], id[x] + size[x] - 1, y, 1);
}
else{
scanf("%lld", &x);
printf("%lld\n", getsum(1, x));
}
}
return 0;
}
P2146
#include
using namespace std;
const int MAXN = 1e5 + 5;
#define lson pos << 1
#define rson pos << 1 | 1
#define len(x) (Tree[x].r - Tree[x].l + 1)
#define lz Tree[pos].lazy
struct edge{
int next, to;
}g[MAXN << 1];
struct Segment_Tree{
int l, r, sum, lazy;
Segment_Tree(){
l = r = sum = 0;
lazy = -1;
}
}Tree[MAXN << 2];
int head[MAXN << 1], cnt;
int n, m, a[MAXN];
int fa[MAXN], d[MAXN], son[MAXN], size[MAXN], top[MAXN], id[MAXN], tmp[MAXN], tot;
void add(int u, int v){
g[++ cnt] = (edge){head[u], v};
head[u] = cnt;
}
void dfs1(int u){
size[u] = 1;
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v == fa[u])continue;
d[v] = d[u] + 1;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[son[u]] < size[v])son[u] = v;
}
}
void dfs2(int u, int front){
top[u] = front, id[u] = ++ tot, tmp[tot] = u;
if(son[u])dfs2(son[u], front);
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v != fa[u] && v != son[u])dfs2(v, v);
}
}
void pushup(int pos){
Tree[pos].sum = Tree[lson].sum + Tree[rson].sum;
}
void pushdown(int pos){
if(lz == -1)return ;
Tree[lson].lazy = Tree[rson].lazy = lz;
Tree[lson].sum = lz * len(lson);
Tree[rson].sum = lz * len(rson);
lz = -1;
}
void build(int pos, int l, int r){
Tree[pos].l = l, Tree[pos].r = r;
if(l == r){
Tree[pos].sum = 0;
return ;
}
int mid = l + r >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
pushup(pos);
}
void update(int l, int r, int k, int pos){
if(Tree[pos].l >= l && Tree[pos].r <= r){
lz = k;
Tree[pos].sum = len(pos) * k;
return ;
}
pushdown(pos);
int mid = Tree[pos].l + Tree[pos].r >> 1;
if(mid >= l)update(l, r, k, lson);
if(mid < r)update(l, r, k, rson);
Tree[pos].sum = Tree[lson].sum + Tree[rson].sum;
}
void change(int l, int r, int x){
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
update(id[top[l]], id[l], x, 1);
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
update(id[l], id[r], x, 1);
}
int main(){
scanf("%d", &n);
for(int i = 2; i <= n; i ++){
int v;
scanf("%d", &v);
v ++;
add(i, v), add(v, i);
}
scanf("%d", &m);
fa[1] = d[1] = 1;
dfs1(1), dfs2(1, 1);
build(1, 1, n);
for(int i = 1; i <= m; i ++){
string opt;
int x;
cin >> opt >> x;
x ++;
int tot = Tree[1].sum;
if(opt == "install"){
change(1, x, 1);
printf("%d\n", abs(Tree[1].sum - tot));
}
else{
update(id[x], id[x] + size[x] - 1, 0, 1);
printf("%d\n", abs(Tree[1].sum - tot));
}
}
return 0;
}
P4092
#include
using namespace std;
const int MAXN = 1e5 + 5;
#define lson pos << 1
#define rson pos << 1 | 1
struct edge{
int next, to;
}g[MAXN << 1];
struct Segment_Tree{
int l, r, deep;
Segment_Tree(){
l = r = 0;
deep = -0x3f3f3f3f;
}
}Tree[MAXN << 2];
int head[MAXN << 1], cnt;
int n, m, a[MAXN];
int fa[MAXN], d[MAXN], son[MAXN], size[MAXN], top[MAXN], id[MAXN], tmp[MAXN], tot;
void add(int u, int v){
g[++ cnt] = (edge){head[u], v};
head[u] = cnt;
}
void dfs1(int u){
size[u] = 1;
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v == fa[u])continue;
d[v] = d[u] + 1;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[son[u]] < size[v])son[u] = v;
}
}
void dfs2(int u, int front){
top[u] = front, id[u] = ++ tot, tmp[tot] = u;
if(son[u])dfs2(son[u], front);
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v != fa[u] && v != son[u])dfs2(v, v);
}
}
void pushup(int pos){
Tree[pos].deep = max(Tree[lson].deep, Tree[rson].deep);
}
void build(int pos, int l, int r){
Tree[pos].l = l, Tree[pos].r = r;
if(l == r)return ;
int mid = l + r >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
}
void update(int l, int r, int pos){
if(Tree[pos].l >= l && Tree[pos].r <= r){
Tree[pos].deep = l;
return ;
}
int mid = Tree[pos].l + Tree[pos].r >> 1;
if(mid >= l)update(l, r, lson);
if(mid < r)update(l, r, rson);
pushup(pos);
}
int query(int pos, int ql, int qr){
if(ql <= Tree[pos].l && Tree[pos].r <= qr)return Tree[pos].deep;
int mid = Tree[pos].l + Tree[pos].r >> 1, maxn = -0x3f3f3f3f;
if(ql <= mid)maxn = max(maxn, query(lson, ql, qr));
if(qr > mid) maxn = max(maxn, query(rson, ql, qr));
return maxn;
}
int getmax(int l, int r){
int res = -0x3f3f3f3f;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res = max(res, query(1, id[top[l]], id[l]));
if(res != -0x3f3f3f3f)return tmp[res];
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
return tmp[query(1, id[l], id[r])];
}
int main(){
scanf("%d %d", &n, &m);
for(int i = 1; i < n; i ++){
int u, v;
scanf("%d %d", &u, &v);
add(u, v), add(v, u);
}
fa[1] = d[1] = 1;
dfs1(1), dfs2(1, 1);
build(1, 1, n);
update(1, 1, 1);
for(int i = 1; i <= m; i ++){
char opt;
int x;
cin >> opt >> x;
if(opt == 'C')update(id[x], id[x], 1);
else printf("%d\n", getmax(x, 1));
}
return 0;
}
P4315
#include
using namespace std;
const int MAXN = 1e5 + 5;
#define lson pos << 1
#define rson pos << 1 | 1
#define len(x) (Tree[x].r - Tree[x].l + 1)
#define lz Tree[pos].lazy
#define tg Tree[pos].tag
#define int long long
struct edge{
int next, to, w;
}g[MAXN << 1];
struct Segment_Tree{
int l, r, maxn, lazy, tag;
Segment_Tree(){
l = r = maxn = lazy = 0;
}
}Tree[MAXN << 2];
int head[MAXN << 1], cnt;
int n, m, r, mod, a[MAXN], b[MAXN];
int fa[MAXN], d[MAXN], son[MAXN], size[MAXN], top[MAXN], id[MAXN], tmp[MAXN], tot;
template<typename T>
void read(T &x){
x = 0;
T f = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){
if(ch == '-')f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= f;
}
template<typename T>
void write(T x){
if(x < 0){
x = -x;
putchar('-');
}
if(x >= 10)write(x / 10);
putchar(x % 10 + 48);
}
void add(int u, int v, int w){
g[++ cnt] = (edge){head[u], v, w};
head[u] = cnt;
}
void dfs1(int u){
size[u] = 1;
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v == fa[u])continue;
a[v] = g[i].w;
d[v] = d[u] + 1;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[son[u]] < size[v])son[u] = v;
}
}
void dfs2(int u, int front){
top[u] = front, id[u] = ++ tot, tmp[tot] = u;
if(son[u])dfs2(son[u], front);
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v != fa[u] && v != son[u])dfs2(v, v);
}
}
void pushup(int pos){
Tree[pos].maxn = max(Tree[lson].maxn, Tree[rson].maxn);
}
void pushdown(int pos){
if(lz >= 0){
Tree[lson].tag = Tree[rson].tag = 0;
Tree[lson].lazy = Tree[rson].lazy = Tree[lson].maxn = Tree[rson].maxn = lz;
lz = -1;
}
if(tg){
Tree[lson].tag += tg, Tree[rson].tag += tg;
Tree[lson].maxn += tg, Tree[rson].maxn += tg;
tg = 0;
}
}
void build(int pos, int l, int r){
Tree[pos].l = l, Tree[pos].r = r, Tree[pos].lazy = -1;
if(l == r){
Tree[pos].maxn = a[tmp[l]];
return ;
}
int mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
pushup(pos);
}
void update(int pos, int k, int x){
if(Tree[pos].l == Tree[pos].r){
Tree[pos].maxn = lz = x;
tg = 0;
return ;
}
pushdown(pos);
int mid = (Tree[pos].l + Tree[pos].r) >> 1;
if(k <= mid)update(lson, k, x);
else update(rson, k, x);
pushup(pos);
}
void update1(int l, int r, int k, int pos){
if(Tree[pos].l >= l && Tree[pos].r <= r){
tg += k;
Tree[pos].maxn += k;
return ;
}
pushdown(pos);
int mid = (Tree[pos].l + Tree[pos].r) >> 1;
if(mid >= l)update1(l, r, k, lson);
if(mid < r)update1(l, r, k, rson);
pushup(pos);
}
void updates1(int l, int r, int x){
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
update1(id[top[l]], id[l], x, 1);
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
update1(id[l] + 1, id[r], x, 1);
}
void update2(int l, int r, int k, int pos){
if(Tree[pos].l >= l && Tree[pos].r <= r){
lz = Tree[pos].maxn = k;
tg = 0;
return ;
}
pushdown(pos);
int mid = (Tree[pos].l + Tree[pos].r) >> 1;
if(mid >= l)update2(l, r, k, lson);
if(mid < r)update2(l, r, k, rson);
pushup(pos);
}
void updates(int l, int r, int x){
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
update2(id[top[l]], id[l], x, 1);
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
update2(id[l] + 1, id[r], x, 1);
}
int query(int pos, int l, int r, int ql, int qr){
if(ql <= l && r <= qr)return Tree[pos].maxn;
int mid = (l + r) >> 1, maxn = -0x3f3f3f3f;
pushdown(pos);
if(ql <= mid)maxn = max(maxn, query(lson, l, mid, ql, qr));
if(qr > mid)maxn = max(maxn, query(rson, mid + 1, r, ql, qr));
return maxn;
}
int getmax(int l, int r){
int res = -0x3f3f3f3f;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res = max(res, query(1, 1, n, id[top[l]], id[l]));
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
return max(res, query(1, 1, n, id[l] + 1, id[r]));
return res;
}
int u[MAXN], v[MAXN], w[MAXN];
signed main(){
read(n);
for(int i = 1; i < n; i ++){
read(u[i]), read(v[i]), read(w[i]);
add(u[i], v[i], w[i]), add(v[i], u[i], w[i]);
}
fa[1] = d[1] = 1;
dfs1(1), dfs2(1, 1);
build(1, 1, n);
for(int i = 1; i < n; i ++){
if(fa[u[i]] == v[i]) son[i] = u[i];
else son[i] = v[i];
}
string opt;
while(1){
cin >> opt;
if(opt == "Stop")break;
int x, y, k;
if(opt == "Change"){
read(x), read(y);
update(1, id[son[x]], y);
}
else if(opt == "Cover"){
read(x), read(y), read(k);
updates(x, y, k);
}
else if(opt == "Add"){
read(x), read(y), read(k);
updates1(x, y, k);
}
else{
read(x), read(y);
write(getmax(x, y));
putchar('\n');
}
}
return 0;
}
P1505
#include
using namespace std;
const int MAXN = 2e5 + 5;
#define lson pos << 1
#define rson pos << 1 | 1
#define lz Tree[pos].lazy
#define int long long
struct edge{
int next, to, w;
}g[MAXN << 1];
struct Segment_Tree{
int l, r, maxn, minn, sum, lazy;
Segment_Tree(){
l = r = lazy = 0;
maxn = -0x3f3f3f3f;
minn = 0x3f3f3f3f;
}
}Tree[MAXN << 2];
int head[MAXN << 1], cnt;
int n, m, r, mod, a[MAXN], b[MAXN];
int fa[MAXN], d[MAXN], son[MAXN], size[MAXN], top[MAXN], id[MAXN], tmp[MAXN], tot;
template<typename T>
void read(T &x){
x = 0;
T f = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){
if(ch == '-')f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= f;
}
template<typename T>
void write(T x){
if(x < 0){
x = -x;
putchar('-');
}
if(x >= 10)write(x / 10);
putchar(x % 10 + 48);
}
void add(int u, int v, int w){
g[++ cnt] = (edge){head[u], v, w};
head[u] = cnt;
}
void dfs1(int u){
size[u] = 1;
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v == fa[u])continue;
a[v] = g[i].w;
d[v] = d[u] + 1;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[son[u]] < size[v])son[u] = v;
}
}
void dfs2(int u, int front){
top[u] = front, id[u] = ++ tot, tmp[tot] = u;
if(son[u])dfs2(son[u], front);
for(int i = head[u]; i; i = g[i].next){
int v = g[i].to;
if(v != fa[u] && v != son[u])dfs2(v, v);
}
}
void pushup(int pos){
Tree[pos].maxn = max(Tree[lson].maxn, Tree[rson].maxn);
Tree[pos].minn = min(Tree[lson].minn, Tree[rson].minn);
Tree[pos].sum = Tree[lson].sum + Tree[rson].sum;
}
void pushdown(int pos){
if(!lz)return ;
Tree[lson].lazy ^= 1, Tree[rson].lazy ^= 1;
Tree[lson].sum = -Tree[lson].sum, Tree[rson].sum = -Tree[rson].sum;
Tree[lson].maxn = -Tree[lson].maxn, Tree[rson].maxn = -Tree[rson].maxn;
Tree[lson].minn = -Tree[lson].minn, Tree[rson].minn = -Tree[rson].minn;
swap(Tree[lson].maxn, Tree[lson].minn);
swap(Tree[rson].maxn, Tree[rson].minn);
lz = 0;
}
void build(int pos, int l, int r){
Tree[pos].l = l, Tree[pos].r = r;
if(l == r){
Tree[pos].minn = Tree[pos].sum = Tree[pos].maxn = a[tmp[l]];
return ;
}
int mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
pushup(pos);
}
void update(int pos, int k, int x){
if(Tree[pos].l == Tree[pos].r){
Tree[pos].maxn = Tree[pos].minn = Tree[pos].sum = x;
return ;
}
pushdown(pos);
int mid = (Tree[pos].l + Tree[pos].r) >> 1;
if(k <= mid)update(lson, k, x);
else update(rson, k, x);
pushup(pos);
}
void update1(int l, int r, int pos){
if(Tree[pos].l >= l && Tree[pos].r <= r){
lz ^= 1;
Tree[pos].sum = -Tree[pos].sum, Tree[pos].maxn = -Tree[pos].maxn, Tree[pos].minn = -Tree[pos].minn;
swap(Tree[pos].maxn, Tree[pos].minn);
return ;
}
pushdown(pos);
int mid = (Tree[pos].l + Tree[pos].r) >> 1;
if(mid >= l)update1(l, r, lson);
if(mid < r)update1(l, r, rson);
pushup(pos);
}
void updates(int l, int r){
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
update1(id[top[l]], id[l], 1);
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
update1(id[l] + 1, id[r], 1);
}
int querymax(int pos, int ql, int qr){
if(ql <= Tree[pos].l && Tree[pos].r <= qr)return Tree[pos].maxn;
int mid = (Tree[pos].l + Tree[pos].r) >> 1, maxn = -0x3f3f3f3f;
pushdown(pos);
if(ql <= mid)maxn = max(maxn, querymax(lson, ql, qr));
if(qr > mid)maxn = max(maxn, querymax(rson, ql, qr));
pushup(pos);
return maxn;
}
int querymin(int pos, int ql, int qr){
if(ql <= Tree[pos].l && Tree[pos].r <= qr)return Tree[pos].minn;
int mid = (Tree[pos].l + Tree[pos].r) >> 1, minn = 0x3f3f3f3f;
pushdown(pos);
if(ql <= mid)minn = min(minn, querymin(lson, ql, qr));
if(qr > mid)minn = min(minn, querymin(rson, ql, qr));
pushup(pos);
return minn;
}
int querysum(int pos, int ql, int qr){
if(ql <= Tree[pos].l && Tree[pos].r <= qr)return Tree[pos].sum;
int mid = (Tree[pos].l + Tree[pos].r) >> 1, sum = 0;
pushdown(pos);
if(ql <= mid)sum += querysum(lson, ql, qr);
if(qr > mid)sum += querysum(rson, ql, qr);
pushup(pos);
return sum;
}
int getmax(int l, int r){
int res = -0x3f3f3f3f;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res = max(res, querymax(1, id[top[l]], id[l]));
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
return max(res, querymax(1, id[l] + 1, id[r]));
}
int getmin(int l, int r){
int res = 0x3f3f3f3f;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res = min(res, querymin(1, id[top[l]], id[l]));
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
return min(res, querymin(1, id[l] + 1, id[r]));
}
int getsum(int l, int r){
int res = 0;
while(top[l] != top[r]){
if(d[top[l]] < d[top[r]])swap(l, r);
res += querysum(1, id[top[l]], id[l]);
l = fa[top[l]];
}
if(d[l] > d[r])swap(l, r);
return (res + querysum(1, id[l] + 1, id[r]));
}
int u[MAXN], v[MAXN], w[MAXN];
signed main(){
read(n);
for(int i = 1; i < n; i ++){
read(u[i]), read(v[i]), read(w[i]);
u[i] ++, v[i] ++;
add(u[i], v[i], w[i]), add(v[i], u[i], w[i]);
}
fa[1] = d[1] = 1;
dfs1(1), dfs2(1, 1);
build(1, 1, n);
for(int i = 1; i < n; i ++){
if(fa[u[i]] == v[i]) son[i] = u[i];
else son[i] = v[i];
}
read(m);
string opt;
while(m --){
cin >> opt;
int x, y;
read(x), read(y);
if(opt == "C"){
update(1, id[son[x]], y);
}
else if(opt == "N"){
updates(x + 1, y + 1);
}
else if(opt == "SUM"){
write(getsum(x + 1, y + 1));
putchar('\n');
}
else if(opt == "MAX"){
write(getmax(x + 1, y + 1));
putchar('\n');
}
else{
write(getmin(x + 1, y + 1));
putchar('\n');
}
}
return 0;
}