洛谷P3313 [SDOI2014]旅行(树链+边权转点权)

洛谷P3313 [SDOI2014]旅行(树链+边权转点权)

#include <bits/stdc++.h>
using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=2e5+100;
int n,m,k,tot,a[maxn],siz[maxn],fa[maxn],son[maxn],id[maxn],idd[maxn],top[maxn],deep[maxn];
int lazy[maxn<<2],sum[maxn<<2],mx[maxn<<2],mn[maxn<<2];
int head[maxn],to[maxn<<1],nex[maxn<<1],w[maxn<<1],vw[maxn*2],tmp[maxn*2];
struct E{int to,next,val;}edge[maxn*2];
struct node{
	int x,y,val;
}e[maxn*2];
void add(int u,int v,int z)
{
    to[++k]=v;
    nex[k]=head[u];
    vw[k]=z;
    head[u]=k;
}
void dfs1(int x,int f,int d){
	siz[x]=1;
	fa[x]=f;
	deep[x]=d;
	son[x]=0;
	for(int i=head[x];i;i=nex[i]){
		int y=to[i];
		if(y==f)continue;
		dfs1(y,x,d+1);
		tmp[y]=vw[i];//边权转点权 
		siz[x]+=siz[y];
		if(siz[son[x]]<siz[y])son[x]=y;
	}
}
void dfs2(int x,int root){
	id[x]=++tot;
	top[x]=root;
	w[tot]=tmp[x];//边权转点权 
	if(son[x])dfs2(son[x],root);
	for(int i=head[x];i;i=nex[i]){
		int y=to[i];
		if(y!=fa[x]&&y!=son[x])dfs2(y,y);
	}
}
void build(int rt,int l,int r){
	if(l==r){
		sum[rt]=mn[rt]=mx[rt]=w[l];
		return;
	}
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
	pushup(rt);
}
int getdis(int x,int y){//边x到y的权值和 
	int ans=0;
	while(top[x]!=top[y]){
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		ans+=query1(1,1,n,id[top[x]],id[x]);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	if(x!=y)ans+=query1(1,1,n,id[x]+1,id[y]);
	return ans;
}
void upday(int x,int y){//x到y区间修改 
	while(top[x]!=top[y]){
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		update(1,1,n,id[top[x]],id[x]);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	if(x!=y)update(1,1,n,id[x]+1,id[y]);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<n;i++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].val);
		add(e[i].x,e[i].y,e[i].val),add(e[i].y,e[i].x,e[i].val);
	}
	dfs1(1,0,1); 
	dfs2(1,1);
	build(1,1,n);
	while(m--){
		int x,y;
		char op[6];
		scanf("%s%d%d",op,&x,&y);
		x++,y++;
		if(op[0]=='C'){
			x--,y--;
			int t;
			if(deep[e[x].x]>deep[e[x].y])t=e[x].x;
			else t=e[x].y;
			updian(1,1,n,id[t],y);
		}
		else if(op[0]=='N')upday(x,y);
		else if(op[0]=='S')printf("%d\n",getdis(x,y));
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值