题目背景
数据规模和spoj上有所不同
题目描述
给定一棵n个节点的树,有两个操作:
CHANGE i ti 把第i条边的边权变成ti
- QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0
输入输出格式
输入格式:第一行输入一个n,表示节点个数
第二行到第n行每行输入三个数,ui,vi,wi,分别表示 ui,vi有一条边,边权是wi
第n+1行开始,一共有不定数量行,每一行分别有以下三种可能
CHANGE,QUERY同题意所述
DONE表示输入结束
对于每个QUERY操作,输出一个数,表示a b之间边权最大值
输入输出样例
输入样例#1:
3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE
输出样例#1:
1 3
说明
数据保证:
1 \leq≤ n \leq≤ 10^5105
操作次数 \leq≤ 3*10^53∗105
wi和ti \leq≤ 2^{31}-1231−1
树链剖分+线段树。
模板水题不解释。。。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x) b[x].data
#define LSIDE(x) b[x].l
#define RSIDE(x) b[x].r
#define MAXN 100010
using namespace std;
int n,m,c=1,d=1;
int head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN];
struct node1{
int next,to,w;
}a[MAXN<<1];
struct node2{
int data,l,r;
}b[MAXN<<2];
struct node3{
int u,v,w;
}g[MAXN];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline void add(int u,int v,int w){
a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
a[c].to=u;a[c].w=w;a[c].next=head[v];head[v]=c++;
}
void dfs1(int rt){
son[rt]=0;size[rt]=1;
for(int i=head[rt];i;i=a[i].next){
int will=a[i].to;
if(!deep[will]){
deep[will]=deep[rt]+1;
fa[will]=rt;
dfs1(will);
size[rt]+=size[will];
if(size[son[rt]]<size[will])son[rt]=will;
}
}
}
void dfs2(int rt,int f){
id[rt]=d++;top[rt]=f;
if(son[rt])dfs2(son[rt],f);
for(int i=head[rt];i;i=a[i].next){
int will=a[i].to;
if(will!=fa[rt]&&will!=son[rt])
dfs2(will,will);
}
}
inline void pushup(int rt){
DATA(rt)=max(DATA(LSON),DATA(RSON));
}
void buildtree(int l,int r,int rt){
int mid;
LSIDE(rt)=l;
RSIDE(rt)=r;
if(l==r){
DATA(rt)=0;
return;
}
mid=l+r>>1;
buildtree(l,mid,LSON);
buildtree(mid+1,r,RSON);
pushup(rt);
}
void update(int l,int r,int c,int rt){
int mid;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
DATA(rt)=c;
return;
}
mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)update(l,r,c,LSON);
if(mid<r)update(l,r,c,RSON);
pushup(rt);
}
int query(int l,int r,int rt){
int mid,ans=0;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);
mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)ans=max(ans,query(l,r,LSON));
if(mid<r)ans=max(ans,query(l,r,RSON));
return ans;
}
void get_max(int x,int y){
int s=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
s=max(s,query(id[top[x]],id[x],1));
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
if(x!=y)s=max(s,query(id[x]+1,id[y],1));
printf("%d\n",s);
return;
}
void work(){
char ch[10];
int x,y;
while(1){
scanf("%s",ch);
if(ch[0]=='D')return;
x=read();y=read();
if(ch[0]=='C'){
g[x].w=y;
update(id[g[x].v],id[g[x].v],y,1);
}
if(ch[0]=='Q'){
if(x==y)printf("0\n");
else get_max(x,y);
}
}
}
void init(){
n=read();
for(int i=1;i<n;i++){
g[i].u=read();g[i].v=read();g[i].w=read();
add(g[i].u,g[i].v,g[i].w);
}
deep[1]=1;
dfs1(1);
dfs2(1,1);
buildtree(1,n,1);
for(int i=1;i<n;i++){
if(deep[g[i].u]>deep[g[i].v])swap(g[i].u,g[i].v);
update(id[g[i].v],id[g[i].v],g[i].w,1);
}
}
int main(){
init();
work();
return 0;
}