我还觉得大家都是把边权拆成点权来做的,结果网上搜不到
查看原帖
我还觉得大家都是把边权拆成点权来做的,结果网上搜不到
368760
chenkejin楼主2021/7/28 18:37

洛谷和网上的题解都是边权下传到点权,再用正常树链剖分,可是更显然的做法不是把一条边拆成两条边一个点,新点的权就是原来的边权

这样甚至都不用考虑边界问题 AC code

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10,M=N*2;
const int INF=10010;
int h[N],e[M],ne[M],idx;
int w[N],top[N],id[N],di[N],son[N],sz[N];
int cnt;
int n;
void add(int a,int b){
	e[idx]=b; ne[idx]=h[a]; h[a]=idx++;
}
struct node{
	int l,r;
	int type,maxv,minv,sum,tag;
}tr[N*4];
void pushup(node &u,node &l,node &r){
	//if(l.type)l.sum=0; if(r.type)r.sum=0;
	u.sum=l.sum+r.sum;
	//if(l.type)l.maxv=-INF; if(r.type) r.maxv=-INF;
	u.maxv=max(l.maxv,r.maxv);
	//if(l.type)l.minv=INF; if(r.type )r.minv=INF;
	u.minv=min(l.minv,r.minv);
}
void pushup(int u){
	pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}
void pushdown(int root){
	node &u=tr[root],&l=tr[root<<1],&r=tr[root<<1|1];
	if(u.tag){
		l.tag^=1; l.sum*=-1; int t=l.maxv; l.maxv=-l.minv; l.minv=-t;
		r.tag^=1; r.sum*=-1; t=r.maxv;     r.maxv=-r.minv; r.minv=-t;
		u.tag=0;
	}
}
void build(int u,int l,int r){
	if(l==r){
		int xx=di[l];
		if(xx>=0&&xx<=n-1)tr[u]={l,r,1,-INF,INF,0,0};
		else tr[u]={l,r,0,w[xx],w[xx],w[xx],0};
	}
	else {
		tr[u]={l,r};
		int  mid=l+r>>1;
		build(u<<1,l,mid); build(u<<1|1,mid+1,r);
		pushup(u);
	}
}
void modify1(int u,int pos,int v){
	if(tr[u].l==tr[u].r){
		tr[u]={pos,pos,0,v,v,v,0};
		return ;
	}
	else {
		pushdown(u);
		int mid=tr[u].l+tr[u].r>>1;
		if(pos<=mid)modify1(u<<1,pos,v);
		else modify1(u<<1|1,pos,v);
		pushup(u);
	}
}
void modify2(int u,int l,int r){
	if(l<=tr[u].l&&tr[u].r<=r){
		node &root=tr[u];
		root.tag^=1; root.sum*=-1; int t=root.maxv; root.maxv=-root.minv; root.minv=-t;
		return;
	}
	else {
		pushdown(u);
		int mid=tr[u].l+tr[u].r>>1;
		if(l<=mid)modify2(u<<1,l,r);
		if(r>mid)modify2(u<<1|1,l,r);
		pushup(u);
	}
}
node query(int u,int l,int r){
	if(l<=tr[u].l&&tr[u].r<=r){
		return tr[u];
	}
	else {
		pushdown(u);
		int mid=tr[u].l+tr[u].r>>1;
		if(r<=mid)return query(u<<1,l,r);
		if(l>mid)return query(u<<1|1,l,r);
		node res,left,right;
		left=query(u<<1,l,r); right=query(u<<1|1,l,r);
		pushup(res,left,right);
		return res;
	}
}
int dep[N],f[N];
void dfs1(int u,int fa,int depth){ 
	dep[u]=depth+1; f[u]=fa; sz[u]=1; son[u]=-1;
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==fa)continue;
		dfs1(j,u,depth+1);
		sz[u]+=sz[j];
		if(son[u]==-1||sz[j]>sz[son[u]])son[u]=j;
	}
}
void dfs2(int u,int fa,int t){
	top[u]=t; id[u]=++cnt; di[cnt]=u;
	if(son[u]==-1)return;
	dfs2(son[u],u,t);
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==fa||j==son[u])continue;		
		dfs2(j,u,j);
	}
}
int query_sum(int u,int v){
	int res=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		res+=query(1,id[top[u]],id[u]).sum;
		u=f[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	res+=query(1,id[v],id[u]).sum;
	return res;
}
void out(int u){
	if(tr[u].l==tr[u].r){
		cout<<tr[u].sum<<' ';
	}
	else {
		pushdown(u);
		int  mid=tr[u].l+tr[u].r>>1;
		out(u<<1); out(u<<1|1);
	}
}
void debug(){
	out(1); cout<<endl;
}
int query_maxv(int u,int v){
	int res=-1002;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		res=max(res,query(1,id[top[u]],id[u]).maxv);
		u=f[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	res=max(res,query(1,id[v],id[u]).maxv);
	return res;
}
int query_minv(int u,int v){
	int res=1002;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		res=min(res,query(1,id[top[u]],id[u]).minv);
		u=f[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	res=min(res,query(1,id[v],id[u]).minv);
	return res;
}
void modify_path(int u,int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		modify2(1,id[top[u]],id[u]);
		u=f[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	modify2(1,id[v],id[u]);
}
int main(){
	scanf("%d",&n);
	memset(h,-1,sizeof h);
	for(int i=0;i<n-1;i++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		add(a,n+i); add(n+i,b);
		add(n+i,a); add(b,n+i);
		w[n+i]=c;
	}
	dfs1(1,1e9,0);
	dfs2(1,1e9,1);
	build(1,1,cnt);
	int m;scanf("%d",&m);
	while(m--){
		//debug();
		char op[5];
		scanf("%s",op);
		//cout<<op<<' ';
		if(!strcmp(op,"C")){
			int i,v;
			scanf("%d%d",&i,&v);
			w[n-1+i]=v;modify1(1,id[n-1+i],v);
		}
		else if(!strcmp(op,"N")){
			int u,v;
			scanf("%d%d",&u,&v); 
			modify_path(u,v);
		}
		else if(!strcmp(op,"SUM")){
			int u,v; scanf("%d%d",&u,&v); 
			cout<<query_sum(u,v)<<endl;
		}
		else if(!strcmp(op,"MAX")){
			int u,v; scanf("%d%d",&u,&v); 
			cout<<query_maxv(u,v)<<endl;
		}
		else {
			int u,v; scanf("%d%d",&u,&v); 
			cout<<query_minv(u,v)<<endl;
		}
	}
}

2021/7/28 18:37
加载中...