这题是我第一次自己查错并且A掉的树剖模板题。
思路很简单,树剖后扔到线段树里就行了。
唯一困难点的是
1.题目给的是边权值,要转为点值,那么直接把值赋给连接边的两点中深度较大的一点
2.修改时,是给编号修改,为了方便,我直接开的几个数组来装边上的信息
//查了半天错,结果是线段树打错了个字母。。。
AC代码如下
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cassert>
#include <sstream>
#include <numeric>
#include <climits>
#include <string>
#include <cctype>
#include <ctime>
#include <iomanip>
#include <cmath>
#include <vector>
#include <queue>
#include <list>
#include <map>
#include <set>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define INF 200100
using namespace std;
struct data{
int to,len,next;
}bian[INF*2];
struct node{
int l,r,sum;
}tr[INF*4];
int n,q,s;
int cnt=0,siz[INF],son[INF],fa[INF],id[INF],top[INF],fanid[INF],deep[INF];
int size,first[INF],a[INF];
bool vis[INF];
int from[INF],too[INF],len[INF],pos,val;
int test,to;
void add(int x,int y,int z)
{
size++;
bian[size].next=first[x];
first[x]=size;
bian[size].to=y;
bian[size].len=z;
}
void init()
{
cnt=size=0;
memset(first,0,sizeof(first));
memset(siz,0,sizeof(siz));
memset(fa,0,sizeof(fa));
memset(deep,0,sizeof(deep));
memset(top,0,sizeof(top));
memset(id,0,sizeof(id));
memset(son,0,sizeof(son));
memset(vis,0,sizeof(vis));
}
void dfs1(int u,int last)
{
vis[u]=1;
siz[u]=1;
fa[u]=last;
deep[u]=deep[last]+1;
for(int i=first[u];i;i=bian[i].next)
{
int to=bian[i].to;
if(to==fa[u]||vis[to])continue;
a[to]=bian[i].len;
dfs1(to,u);
siz[u]+=siz[to];
if(son[u]==0)son[u]=to;
else if(siz[son[u]]<siz[to])
son[u]=to;
}
}
void dfs2(int u,int topp)
{
vis[u]=1;
id[u]=++cnt;
top[u]=topp;
fanid[cnt]=u;
if(son[u])dfs2(son[u],topp);
for(int i=first[u];i;i=bian[i].next)
{
int to=bian[i].to;
if(to==fa[u]||to==son[u]||vis[to])continue;
dfs2(to,to);
}
}
void update(int k)
{
tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
}
void build(int k,int s,int t)
{
tr[k].l=s;tr[k].r=t;
if(s==t)
{
tr[k].sum=a[fanid[s]];
return;
}
int mid=s+t>>1;
build(k<<1,s,mid);
build(k<<1|1,mid+1,t);
update(k);
}
void modify(int k,int pos,int val)
{
if(tr[k].l==tr[k].r){
tr[k].sum=val;
return;
}
int mid=tr[k].l+tr[k].r>>1;
if(pos<=mid)modify(k<<1,pos,val);
else modify(k<<1|1,pos,val);
update(k);
}
int query(int k,int s,int t)
{
if(s<=tr[k].l&&tr[k].r<=t)
return tr[k].sum;
int mid=tr[k].l+tr[k].r>>1;
int res=0;
if(t<=mid)
res+=query(k<<1,s,t);
else
if(s>mid)
res+=query(k<<1|1,s,t);
else
res+=query(k<<1,s,mid)+query(k<<1|1,mid+1,t);
return res;
}
int solvequery(int x,int y)
{
int sum=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
sum+=query(1,id[top[x]],id[x]);
x=fa[top[x]];
}
if(x==y)return sum;
if(deep[x]>deep[y])swap(x,y);
sum+=query(1,id[x]+1,id[y]);
return sum;
}
int main()
{
// freopen("in.in","r",stdin);
while(scanf("%d%d%d",&n,&q,&s)!=EOF)
{
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&from[i],&too[i],&len[i]);
add(from[i],too[i],len[i]);
add(too[i],from[i],len[i]);
}
dfs1(1,0);
memset(vis,0,sizeof(vis));
dfs2(1,1);
for(int i=1;i<n;i++)
{
if(deep[from[i]]<deep[too[i]])
swap(from[i],too[i]);
a[from[i]]=len[i];
}
build(1,1,n);
while(q--)
{
scanf("%d",&test);
if(test){
scanf("%d%d",&pos,&val);
modify(1,id[from[pos]],val);
}
else{
scanf("%d",&to);
cout<<solvequery(s,to)<<endl;
s=to;
}
}
}
}