大致题意:
给定一棵树,有两种操作:
1:Q x y 表示询问树上x~y的路径上的最大权值
2:C x y 表示修改第x条边的权值为y
3:Done 结束这组输入
输入格式
输入数据第一行一个正整数T,代表一共有T组数据。
接下来每组数据,第一行一个正整数N,意义如题面所示。
接下来N-1行,每行三个整数x、y、w描述一条枝干,分别代表这条枝干连接的两个结点的编号和这条枝干的初始长度。
接下来不知道多少行,每行一个字符串s和两个整数x、y,若s为”QUERY”,请输出结点x到y之间所有枝干最粗的粗细;若s为”CHANGE”,请将编号为x的枝干粗细改为y;若s为”DONE”,则本组数据结束。
输出格式
输出数据不知道多少行,对于每个询问操作,输出其答案。
input
1
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
output
1
3
数据规模与约定
T≤20,N≤10000,w≤1000000。
树剖板子题。
修改操作没有看清楚题目直接对编号为x的节点的父边修改了QAQ,调了好久
#include<bits/stdc++.h>
using namespace std;
#define ls root * 2
#define rs root * 2 + 1
int n , Q , linkk[101000] , t;
int size[101000] , son[101000] , fa[101000] , dep[101000];
int top[101000] , w[101000] , totw , tmp[101000];
int tr[401000];
struct node{
int n , y , v;
}e[201000];
int read()
{
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
void insert(int x,int y,int z)
{
e[++t].y = y;e[t].n = linkk[x];e[t].v = z;linkk[x] = t;
e[++t].y = x;e[t].n = linkk[y];e[t].v = z;linkk[y] = t;
return;
}
void dfs1(int x,int f)
{
dep[x] = dep[f] + 1;
fa[x] = f;
int Max = 0;
for(int i = linkk[x];i;i = e[i].n)
if(e[i].y != f)
{
int y = e[i].y;
dfs1(y , x);
size[x] += size[y];
if(size[y] > Max) son[x] = y , Max = size[y];
}
size[x]++;
}
void dfs2(int x)
{
if(x != 1)w[x] = ++totw;
top[x] = x == son[fa[x]] ? top[fa[x]] : x;
if(son[x])dfs2(son[x]);
for(int i = linkk[x];i;i = e[i].n)
if(e[i].y != fa[x] && e[i].y != son[x])
dfs2(e[i].y);
return;
}
int Lca(int x,int y)
{
for(;top[x] != top[y];)
dep[top[x]] > dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
return dep[x] < dep[y] ? x : y;
}
void build(int root,int l,int r)
{
if(l == r)
{
tr[root] = tmp[l];
return;
}
int mid = (l + r)>>1;
build(ls , l , mid);
build(rs , mid + 1 , r);
tr[root] = max(tr[ls] , tr[rs]);
return;
}
int query(int root,int l,int r,int x,int y)
{
if( r < x || l > y ) return 0;
if( x <= l && y >= r ) return tr[root];
int mid = (l + r)>>1;
return max( query(ls , l , mid , x , y) , query(rs , mid + 1 , r , x , y) );
}
int ask(int a,int b)
{
int ans = 0;
if(a == b) return ans;
int ta = top[a] , tb = top[b];
while(ta != tb)
{
if(dep[ta] < dep[tb])
swap(ta , tb) , swap(a , b);
ans = max(ans , query(1 , 1 , n - 1, w[ta] , w[a]));
a = fa[ta];
ta = top[a];
}
if(a == b) return ans;
if(dep[a] > dep[b]) swap(a , b) , swap(ta , tb);
ans = max(ans , query(1 , 1 , n - 1,w[son[a]] , w[b]));
return ans;
}
void change(int root,int l,int r,int pl,int v)
{
if(l == r)
{
tr[root] = v;
return;
}
int mid = (l + r)>>1;
if(pl <= mid) change(ls , l , mid , pl , v);
else change(rs , mid + 1 , r , pl , v);
tr[root] = max(tr[ls] , tr[rs]);
return;
}
void init()
{
memset(linkk , 0 , sizeof(linkk));
memset(tr , 0 , sizeof(tr));
memset(son , 0 , sizeof(son));
memset(size , 0 , sizeof(size));
t = 0;totw = 0;
n = read();
for(int i = 1;i < n;++i)
{
int x = read() , y = read() , z = read();
insert(x , y , z);
}
dfs1(1 , 0);
dfs2(1);
for(int x = 1;x <= n;++x)
for(int i = linkk[x];i;i = e[i].n)
if(e[i].y != fa[x])
tmp[ w[e[i].y] ] = e[i].v;
build(1,1,n - 1);
while(1)
{
char c = getchar();
while(c != 'Q' && c != 'C' && c != 'D') c = getchar();
if(c == 'D') break;
int x = read() , y = read();
if(c == 'Q') printf("%d\n",ask(x , y));
else
{
int a = dep[e[2 * x - 1].y] , b = dep[e[2 * x].y];
x = a < b ? e[2 * x].y : e[2 * x - 1].y;
change(1 , 1 , n - 1 , w[x] , y);
}
}
return;
}
int main()
{
int T = read();
while(T--) init();
return 0;
}