#树链剖分,线段树#洛谷 4315 月下毛景树

题目


分析

修改操作到了边上,考虑把这个修改转到节点,那么就是道树链剖分的模板了,但是要加一个标记表示区间赋值


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=100101; struct node{int y,w,next;}e[N<<1];
int w[N<<2],lazy[N<<2],lyza[N<<2],dfn[N],top[N],dep[N],n,K=1,fat[N],a[N],A[N],son[N],ls[N],big[N],tot;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline signed max(int a,int b){return a>b?a:b;}
inline void build(int k,int l,int r){
	lyza[k]=-1;
	if (l==r){
		w[k]=a[l];
		return;
	}
	rr int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	w[k]=max(w[k<<1],w[k<<1|1]);
} 
inline void pdown(int k){
	if (lyza[k]>=0){
		lyza[k<<1]=lyza[k<<1|1]=w[k<<1]=w[k<<1|1]=lyza[k];
		lazy[k<<1]=lazy[k<<1|1]=0,lyza[k]=-1;
	}
	if (lazy[k]){
		lazy[k<<1]+=lazy[k],lazy[k<<1|1]+=lazy[k];
		w[k<<1]+=lazy[k],w[k<<1|1]+=lazy[k],lazy[k]=0;
	}
}
inline void update(int k,int l,int r,int x,int y,int z,int bel){
	if (l==x&&r==y){
		if (!bel) lazy[k]+=z,w[k]+=z;
		    else w[k]=lyza[k]=z,lazy[k]=0;
		return;
	}
	rr int mid=(l+r)>>1; pdown(k);
	if (y<=mid) update(k<<1,l,mid,x,y,z,bel);
	else if (x>mid) update(k<<1|1,mid+1,r,x,y,z,bel);
	else update(k<<1,l,mid,x,mid,z,bel),update(k<<1|1,mid+1,r,mid+1,y,z,bel);
	w[k]=max(w[k<<1],w[k<<1|1]);
}
inline signed query(int k,int l,int r,int x,int y){
	if (l==x&&r==y) return w[k];
	rr int mid=(l+r)>>1; pdown(k);
	if (y<=mid) return query(k<<1,l,mid,x,y);
	else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
	else return max(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y)); 
}
inline void Update(int x,int y,int z,int bel){
	for (;top[x]!=top[y];x=fat[top[x]]){
		if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
		update(1,1,n,dfn[top[x]],dfn[x],z,bel);
	}
	if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
	if (dfn[x]<dfn[y]) update(1,1,n,dfn[x]+1,dfn[y],z,bel);
}
inline signed Query(int x,int y){
	rr int ans=0;
	for (;top[x]!=top[y];x=fat[top[x]]){
		if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
		ans=max(ans,query(1,1,n,dfn[top[x]],dfn[x]));
	}
	if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
	if (dfn[x]<dfn[y]) ans=max(ans,query(1,1,n,dfn[x]+1,dfn[y])); 
	return ans;
}
inline void dfs1(int x,int fa){
	dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
	for (rr int i=ls[x],mson=-1;i;i=e[i].next)
	if (e[i].y!=fa){
		dfs1(e[i].y,x); A[e[i].y]=e[i].w;
		son[x]+=son[e[i].y];
		if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y];
	}
}
inline void dfs2(int x,int linp){
	dfn[x]=++tot,top[x]=linp,a[dfn[x]]=A[x];
	if (!big[x]) return; dfs2(big[x],linp);
	for (rr int i=ls[x];i;i=e[i].next)
	    if (e[i].y!=fat[x]&&e[i].y!=big[x])
	        dfs2(e[i].y,e[i].y);
}
signed main(){
	n=iut();
	for (rr int i=1;i<n;++i){
		rr int x=iut(),y=iut(),w=iut();
		e[++K]=(node){y,w,ls[x]},ls[x]=K;
		e[++K]=(node){x,w,ls[y]},ls[y]=K;
	}
	dfs1(1,0),dfs2(1,1),build(1,1,n);
	rr char ss[5];
	while (1){
		scanf("%s",ss);
		if (ss[0]=='S') return 0;
		rr int x=iut(),y=iut();
        switch (ss[0]){
        	case 'C':{
        		if (ss[1]=='o') Update(x,y,iut(),1);
				    else Update(e[x<<1].y,e[x<<1|1].y,y,1);
				break;
			}
			case 'A':{
				Update(x,y,iut(),0);
				break;
			}
			case 'M':{
				print(Query(x,y)),putchar(10);
				break;
			}
		} 
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值