其实呢,这题很简单,树链剖分的板子题,基本不会错,就算错误大概是RE(runtime error),为什么会这么说呢?你如果判断当前是什么操作的op是longlong类型,那恭喜你喜提一发RE,只有int才能够刚刚好过去,很神奇,很奇妙,百思不得其解。
题解:将树重链剖分后,然后用线段树或树状数组等结构维护得到的dfs序即可,由于权为边权而非点权,那么只要将边权设两点间深度较深的那点为点权即可将边权转为点权
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<ctime>
#include<algorithm>
#include<sstream>
#include<bitset>
#define scand(a) scanf("%d",&a)
#define scandd(a,b) scanf("%d%d",&a,&b)
#define scanddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mst(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x&-x)
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fLL;
const int maxn=1e5+5;
const ll mod=1e9+7;
struct nod
{
int nxt,to;
}edge[maxn<<1];
int head[maxn],cnt=1;
void add(int u,int v)
{
edge[++cnt].nxt=head[u];
edge[cnt].to=v;
head[u]=cnt;
}
int f[maxn],dep[maxn],size[maxn],son[maxn],rnk[maxn],tp[maxn],id[maxn],tot,rt,n,m;
ll uu[maxn],vv[maxn],ww[maxn];
ll tre[maxn<<2];
void upd(int rt,int l,int r,int pos,ll w)
{
if(l==r)
{
tre[rt]=w;
return;
}
int mid=l+r>>1;
if(pos<=mid)upd(lson,l,mid,pos,w);
else upd(rson,mid+1,r,pos,w);
tre[rt]=tre[lson]+tre[rson];
}
void dfs1(int u,int fa,int depth)
{
f[u]=fa;
size[u]=1;
dep[u]=depth;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa)continue;
dfs1(v,u,depth+1);
size[u]+=size[v];
if(size[v]>size[son[u]])son[u]=v;
}
}
void dfs2(int u,int t)
{
tp[u]=t;
id[u]=++tot;
if(son[u])dfs2(son[u],t);
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v!=son[u]&&v!=f[u])dfs2(v,v);
}
}
ll que(int rt,int l,int r,int pl,int pr)
{
if(pl<=l&&r<=pr)
{
return tre[rt];
}
ll sum=0;
int mid=l+r>>1;
if(pl<=mid)sum+=que(lson,l,mid,pl,pr);
if(pr>mid)sum+=que(rson,mid+1,r,pl,pr);
return sum;
}
void ans(int x,int y)
{
ll sum=0;
while(tp[x]!=tp[y])
{
if(dep[tp[x]]<dep[tp[y]])swap(x,y);
sum+=que(1,1,n,id[tp[x]],id[x]);
x=f[tp[x]];
}
if(id[x]>id[y])swap(x,y);
if(x!=y) //由于是问的两点间的路费,显然同一点是不用路费的
sum+=que(1,1,n,id[son[x]],id[y]);
/*
因为边权转点权,所以如果用的是id[x]的话,显然会多算一段边权进来
*/
printf("%lld\n",sum);
}
int main()
{
#ifdef local
freopen("1.txt","r",stdin);
// freopen("2.txt","w",stdout);
#endif
while(~scandd(n,m))
{
cnt=1,tot=0;
mst(tre,0);
mst(head,0);
mst(son,0);
mst(dep,0);
mst(edge,0);
for(int i=1;i<=n-1;i++)
{
scanf("%lld%lld%lld",&uu[i],&vv[i],&ww[i]);
add(uu[i],vv[i]);
add(vv[i],uu[i]);
}
dfs1(1,0,1);
dfs2(1,1);
for(int i=1;i<=n-1;i++)
{
if(dep[uu[i]]<dep[vv[i]])swap(uu[i],vv[i]);
upd(1,1,n,id[uu[i]],ww[i]);
}
for(int i=0;i<m;i++)
{
int op;ll a,b;
scanf("%d%lld%lld",&op,&a,&b);
if(op==0)
{
upd(1,1,n,id[uu[a]],b);
}
else ans(a,b);
}
}
}