[樹剖] 月下“毛景樹” (咕)

月下“毛景樹”

此題不板,何板之有?
是不板,孰板?

T1,需要邊權下放到點權,考慮 DFS1 的時候就下放
注意 LCA 不能算進去

注意要先cover

gigo 大佬是算了 LCA ,調了一下午,我是沒考慮 coveradd 操作的優先級,調了一下午
coveradd 要優先一些,因爲 coveradd 就沒用了

單獨下放邊權,思路比較清晰一些(giaohr巨巨的代碼;並且我請求大家不要訪問他的博客,因爲這樣會增加他的訪問量)

#include<bits/stdc++.h>
#define in Read()
#define int long long
using namespace std;
inline int in{
	int i=0,f=1;char ch;
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')ch=getchar(),f=-1;
	while(isdigit(ch))i=(i<<1)+(i<<3)+ch-48,ch=getchar();
	return i*f;
}

const int NNN=1e5+5;
const int INF=1e9+7;
int n;
char q[50];
int tot;
int first[NNN];
int nxt[NNN<<1];
int aim[NNN<<1];
int wei[NNN];
int to1[NNN];
int to2[NNN];
int faz[NNN];
int dep[NNN];
int siz[NNN];
int son[NNN];
int top[NNN];
int dfn[NNN];
int idx[NNN];
int dwn[NNN];
int val[NNN];
int ord;
struct Tree{
	int l,r;
	int max;
	int add;
	int cov;
}tre[NNN<<2];

inline void add(int u,int v){
	++tot;
	nxt[tot]=first[u];
	first[u]=tot;
	aim[tot]=v;
	return;
}

inline void DFS1(int fa,int u){
	faz[u]=fa;
	dep[u]=dep[fa]+1;
	siz[u]=1;
	for(int e=first[u];e;e=nxt[e]){
		int v=aim[e];
		if(v==fa) continue;
		DFS1(u,v);
		siz[u]+=siz[v];
		if(siz[son[u]]<siz[v]) son[u]=v;
	}
	return;
}

inline void DFS2(int u,int tp){
	top[u]=tp;
	dfn[u]=++ord;
	idx[ord]=u;
	if(!son[u]) return;
	DFS2(son[u],tp);
	for(int e=first[u];e;e=nxt[e]){
		int v=aim[e];
		if(v==faz[u]||v==son[u]) continue;
		DFS2(v,v);
	}
	return;
}

inline void push_road(){
	for(int i=1;i<n;++i){
		dwn[i]=dep[to1[i]]<dep[to2[i]]?to2[i]:to1[i];
		val[dwn[i]]=wei[i];
	}
	return;
}

#define lch p<<1
#define rch p<<1|1
#define tr tre[p].r
#define tl tre[p].l

inline void push_up(int p){
	tre[p].max=max(tre[lch].max,tre[rch].max);
	return ;
}

inline void push_down(int p){
	if(tre[p].cov!=-1){
		tre[lch].max=tre[p].cov;
		tre[rch].max=tre[p].cov;
		tre[lch].cov=tre[p].cov;
		tre[rch].cov=tre[p].cov;
		tre[lch].add=0;
		tre[rch].add=0;
		tre[p].cov=-1;
	}
	if(tre[p].add){
		tre[lch].add+=tre[p].add;
		tre[rch].add+=tre[p].add;
		tre[lch].max+=tre[p].add;
		tre[rch].max+=tre[p].add;
		tre[p].add=0;
	}
	return;
}

inline void build(int p,int l,int r){
	tr=r,tl=l;
	tre[p].cov=-1;
	tre[p].max=-INF;
	if(l==r){
		tre[p].max=val[idx[l]];
		return;
	}
	int mid=l+r>>1;
	build(lch,l,mid);
	build(rch,mid+1,r);
	push_up(p);
	return;
}

inline void cover(int p,int l,int r,int w){
	if(l<=tl&&tr<=r){
		tre[p].max=w;
		tre[p].cov=w;
		tre[p].add=0;
		return;
	}
	push_down(p);
	int mid=tl+tr>>1;
	if(l<=mid) cover(lch,l,r,w);
	if(r>mid) cover(rch,l,r,w);
	push_up(p);
	return;
}

inline void update(int p,int l,int r,int w){
	if(l<=tl&&tr<=r){
		tre[p].max+=w;
		tre[p].add+=w;
		return;
	}
	push_down(p);
	int mid=tr+tl>>1;
	if(l<=mid) update(lch,l,r,w);
	if(r>mid) update(rch,l,r,w);
	push_up(p);
	return;
}

inline int query(int p,int l,int r){
	if(l<=tl&&tr<=r) return tre[p].max;
	int ans=0;
	push_down(p);
	int mid=tr+tl>>1;
	if(l<=mid) ans=max(ans,query(lch,l,r));
	if(r>mid) ans=max(ans,query(rch,l,r));
	return ans;
}

#undef lch
#undef rch
#undef tr
#undef tl

inline void Cover(int u,int v,int w){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		cover(1,dfn[top[u]],dfn[u],w);
		u=faz[top[u]];
	}
	if(u==v) return;
	if(dep[u]>dep[v]) swap(u,v);
	cover(1,dfn[u]+1,dfn[v],w);
	return;
}

inline void Add(int u,int v,int w){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		update(1,dfn[top[u]],dfn[u],w);
		u=faz[top[u]];
	}
	if(u==v) return;
	if(dep[u]>dep[v]) swap(u,v);
	update(1,dfn[u]+1,dfn[v],w);
	return;
}

inline int Query(int u,int v){
	int ans=-INF;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ans=max(ans,query(1,dfn[top[u]],dfn[u]));
		u=faz[top[u]];
	}
	if(u==v) return ans;
	if(dep[u]>dep[v]) swap(u,v);
	ans=max(ans,query(1,dfn[u]+1,dfn[v]));
	return ans;	
}

signed main(){
	
//	freopen("moon.in","r",stdin);
//	freopen("moon.out","w",stdout);
	
	n=in;
	for(int i=1;i<n;++i){
		int u=in,v=in,w=in;
		add(u,v);
		add(v,u);
		to1[i]=u;
		to2[i]=v;
		wei[i]=w;
	}
	DFS1(0,1);
	DFS2(1,1);
	push_road();
	build(1,1,n);
	scanf("%s",q);
	while(q[0]!='S'){
		if(q[1]=='h'){
			int k=in,w=in;
			cover(1,dfn[dwn[k]],dfn[dwn[k]],w);
		}else if(q[1]=='o'){
			int u=in,v=in,w=in;
			Cover(u,v,w);
		}else if(q[1]=='d'){
			int u=in,v=in,w=in;
			Add(u,v,w);
		}else if(q[1]=='a'){
			int u=in,v=in;
			printf("%lld\n",Query(u,v));
		}scanf("%s",q);
	}
	return 0;
}

另外的DFS1就下放的代碼,我先咕了~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章