[樹剖] 200612Practice T1 Travel

Travel

考試題,考場上樹剖4K碼炸了,整出來了一個只能正確求出從深度大的點走到深度小的點的代碼

考慮維護幾個值:(樹剖你維護就是了,主要是要想清楚要維護什麼
區間 max,區間 min,兩個方向的利潤最大值( forward , bakward ),當然還需要 lazy_tag

其中forwardp=max{forwardlch,forwardrch,maxxlchminnrch}bakwardp=max{bakwardlch,bakwardrch,maxxrchminnlch}forward_p=\max\{ forward_{lch}, forward_{rch},maxx_{lch}-minn_{rch}\}\\bakward_p=\max\{ bakward_{lch}, bakward_{rch},maxx_{rch}-minn_{lch}\}

變量名取長了就醜

調了一個晚上😭
(不過機房人誰不是這樣的呢)
但是最後發現是我用了C++11,洛谷炸了

洛谷傻逼
#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+10;
const int INF=1e9+10;
int n,q;
int tot;
vector<int>G[NNN];
int wei[NNN];//u->value
int faz[NNN];
int son[NNN];
int dep[NNN];
int dfn[NNN];
int idx[NNN];//inverse map of dfn
int ord;//dfs order
int siz[NNN];
int top[NNN];
int sgn[NNN];//to mark whether to take forward or backward
struct SGT{
	int l,r;
	int max_;
	int min_;
	int lmax;//go from down to up, forward
	int rmax;//go from up to down, backward
	int lazy;
	
	inline void Clear(){
		max_=0;
		min_=INF;
		lmax=0;
		rmax=0;
		return;
	}
	
}tre[NNN<<2];

inline void DFS1(int fa,int u){
	faz[u]=fa;
	dep[u]=dep[fa]+1;
	siz[u]=1;
	for(int e=0;e<G[u].size();++e){
		int v=G[u][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 qwq){
	dfn[u]=++ord;
	top[u]=qwq;
	idx[ord]=u;
	if(!son[u]) return;
	DFS2(son[u],qwq);
	for(int e=0;e<G[u].size();e++){
		int v=G[u][e];
		if(v==faz[u]||v==son[u]) continue;
		DFS2(v,v);
	}
	return;
}

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

inline void push_up(int p){
	tre[p].max_=max(tre[lch].max_,tre[rch].max_);
	tre[p].min_=min(tre[lch].min_,tre[rch].min_);
	tre[p].lmax=max(tre[lch].max_-tre[rch].min_,max(tre[lch].lmax,tre[rch].lmax));
	tre[p].rmax=max(tre[rch].max_-tre[lch].min_,max(tre[lch].rmax,tre[rch].rmax));
	return;
}

inline void push_down(int p){
	if(!tre[p].lazy) return;
	tre[lch].max_+=tre[p].lazy;
	tre[rch].max_+=tre[p].lazy;
	tre[lch].min_+=tre[p].lazy;
	tre[rch].min_+=tre[p].lazy;
	tre[lch].lazy+=tre[p].lazy;
	tre[rch].lazy+=tre[p].lazy;
	tre[p].lazy=0;
	return;
}

inline SGT merge(SGT l,SGT r){
	SGT res;
	res.max_=max(l.max_,r.max_);
	res.min_=min(l.min_,r.min_);
	res.lmax=max(l.max_-r.min_,max(l.lmax,r.lmax));
	res.rmax=max(r.max_-l.min_,max(l.rmax,r.rmax));
	return res;
}

inline void build(int p,int l,int r){
	tl=l;tr=r;
	if(l==r){
		tre[p].max_=wei[idx[l]];
		tre[p].min_=wei[idx[l]];
		return;
	}
	int mid=l+r>>1;
	build(lch,l,mid);
	build(rch,mid+1,r);
	push_up(p);
	return;
}

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

inline void update(int p,int l,int r,int w){
	if(l<=tl&&tr<=r){
		tre[p].max_+=w;
		tre[p].min_+=w;
		tre[p].lazy+=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;
}

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

inline int Sum(int u,int v){
	SGT l,r;
	l.Clear();r.Clear();
	l.min_=INF;
	r.min_=INF;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]){
			r=merge(query(1,dfn[top[v]],dfn[v]),r);
			v=faz[top[v]];
		}else{
			l=merge(query(1,dfn[top[u]],dfn[u]),l);
			u=faz[top[u]];
		}
	}
	if(dep[u]>dep[v]) l=merge(query(1,dfn[v],dfn[u]),l);
	else r=merge(query(1,dfn[u],dfn[v]),r);
	swap(l.lmax,l.rmax);
	return merge(l,r).rmax;
}

inline void Modify(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(dep[u]>dep[v]) swap(u,v);
	update(1,dfn[u],dfn[v],w);
	return;
}

signed main(){
//	freopen("my.out","w",stdout);
	n=in;
	for(int i=1;i<=n;++i) wei[i]=in;
	for(int i=2;i<=n;++i){
		int u=in,v=in;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	DFS1(0,1);
	DFS2(1,1);
	build(1,1,n);
	q=in;
	for(int i=1;i<=q;++i){
		int u=in,v=in,w=in;
		printf("%lld\n",Sum(u,v));
		Modify(u,v,w);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章