【CC】Batman and Tree

Portal --> CC Batman and Tree

Solution

  一开始看到很懵。。感觉无从下手(因为自己太菜了qwq)

​  膜拜了题解之后发现好像并没有想象的那么复杂qwq

​  其实冷静下来考虑dp,用(f[i])表示当前在(i)的最大能量值,然后对于一个从(x)(y)的强盗,考虑找一条路径满足(x)(y)的简单路径是其子路径,那么我们就可以用满足条件的路径的端点(f)值的最大值来更新走到的另一个端点处的新(f)

​  将dfs序处理出来,不难发现满足条件的路径的端点对应的应该是几段区间,具体一点就是(默认(dep[x]<=dep[y])):

(1)(x)(y)的祖先,此时记(dw)为满足(yin subtree(dw))(dwin son(x))的节点,那么可以选路径的的端点应该一个在区间([1,st[dw]]cup[ed[dw]+1,n])内,一个在([st[y],ed[y]])

(2)(x)不是(y)的祖先,那么此时可以选路径的端点应该一个在([st[x],ed[x]]),一个在([st[y],ed[y]])

  那么直接线段树维护一下就好了,实现一个区间取max和区间查询max即可(吉老师线段树)
  

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=4e5+10,TOP=20;
const ll inf=1LL<<60;
struct xxx{
	int y,nxt;
}a[N*2];
int h[N],lis[N],dep[N];
int st[N],ed[N],f[N][TOP+1];
int n,m,tot,dfn_t,dfn_t1;
int S,P,T;
namespace Seg{/*{{{*/
	const int N=::N*4;
	int ch[N][2];
	ll tag[N],mx[N],smx[N],mn[N],smn[N];
	int n,tot;
	void pushup(int x){
		if (mx[ch[x][0]]==mx[ch[x][1]]){
			mx[x]=mx[ch[x][0]];
			smx[x]=max(smx[ch[x][0]],smx[ch[x][1]]);
		}
		else{
			int lw,up;
			if (mx[ch[x][0]]>mx[ch[x][1]]) up=0,lw=1;
			else up=1,lw=0;
			mx[x]=mx[ch[x][up]];
			smx[x]=max(smx[ch[x][up]],mx[ch[x][lw]]);
		}

		if (mn[ch[x][0]]==mn[ch[x][1]]){
			mn[x]=mn[ch[x][0]];
			smn[x]=min(smn[ch[x][0]],smn[ch[x][1]]);
		}
		else{
			int lw,up;
			if (mn[ch[x][0]]<mn[ch[x][1]]) lw=0,up=1;
			else lw=1,up=0;
			mn[x]=mn[ch[x][lw]];
			smn[x]=min(smn[ch[x][lw]],mn[ch[x][up]]);
		}
	}
	void _build(int x,int l,int r){
		smx[x]=-inf; smn[x]=inf; tag[x]=0;
		if (l==r){mx[x]=mn[x]=(::lis[l]==S?P:-inf);return;}
		int mid=l+r>>1;
		ch[x][0]=++tot; _build(ch[x][0],l,mid);
		ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
		pushup(x);
	}
	void build(int _n){n=_n; tot=1; _build(1,1,n);}
	void give_mxtag(int x,ll delta){
		mn[x]=delta;
		mx[x]=max(mx[x],delta);
		tag[x]=max(tag[x],delta);
		if (mn[x]==mx[x])
			smn[x]=inf,smx[x]=-inf;
		else
			smx[x]=max(smx[x],delta);
	}
	void downtag(int x){
		if (!tag[x]) return;
		if (ch[x][0]) 
			if (mn[ch[x][0]]<mn[x]&&mn[x]<smn[ch[x][0]])
				give_mxtag(ch[x][0],tag[x]);
		if (ch[x][1]) 
			if (mn[ch[x][1]]<mn[x]&&mn[x]<smn[ch[x][1]])
				give_mxtag(ch[x][1],tag[x]);
		tag[x]=0;
	}
	void _update(int x,int l,int r,int lx,int rx,ll delta){
		if (mn[x]>=delta) return;
		if (l<=lx&&rx<=r&&delta<smn[x]){
			give_mxtag(x,delta);
			return;
		}
		downtag(x);
		int mid=lx+rx>>1;
		if (r<=mid) _update(ch[x][0],l,r,lx,mid,delta);
		else if (l>mid) _update(ch[x][1],l,r,mid+1,rx,delta);
		else{
			_update(ch[x][0],l,mid,lx,mid,delta);
			_update(ch[x][1],mid+1,r,mid+1,rx,delta);
		}
		pushup(x);
	}
	void update(int l,int r,ll delta){if (l<=r) _update(1,l,r,1,n,delta);}
	ll _query(int x,int l,int r,int lx,int rx){
		if (l<=lx&&rx<=r) return mx[x];
		downtag(x);
		int mid=lx+rx>>1;
		if (r<=mid) return _query(ch[x][0],l,r,lx,mid);
		else if (l>mid) return _query(ch[x][1],l,r,mid+1,rx);
		else 
			return max(_query(ch[x][0],l,mid,lx,mid),_query(ch[x][1],mid+1,r,mid+1,rx));
	}
	ll query(int l,int r){return l>r?-inf:_query(1,l,r,1,n);}
	void _debug(int x,int lx,int rx){
		if (lx==rx){printf("%lld ",mx[x]); return;}
		downtag(x);
		int mid=lx+rx>>1;
		_debug(ch[x][0],lx,mid);
		_debug(ch[x][1],mid+1,rx);
	}
	void debug(){_debug(1,1,n);}
}/*}}}*/
void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
void dfs(int fa,int x,int d){
	int u;
	lis[++dfn_t]=x;
	st[x]=dfn_t; dep[x]=d;
	f[x][0]=fa;
	for (int i=1;i<=TOP;++i) f[x][i]=f[f[x][i-1]][i-1];
	for (int i=h[x];i!=-1;i=a[i].nxt){
		u=a[i].y;
		if (u==fa) continue;
		dfs(x,u,d+1);
	}
	ed[x]=dfn_t;
}
int jump(int x,int d){
	if (d==0) return x;
	for (int i=0;i<=TOP;++i)
		if (d>>i&1) x=f[x][i];
	return x;
}
void debug(){
	for (int i=1;i<=n;++i) printf("%lld ",Seg::query(i,i)); printf("
");
}
void modify(int x,int y,int r,int t){
	ll tmp1,tmp2;
	int dw;
	//dep[x]<dep[y]
	if (dep[x]>dep[y]) swap(x,y);
	if (st[x]<=st[y]&&st[y]<=ed[x]){
		dw=jump(y,dep[y]-dep[x]-1);
		tmp1=max(Seg::query(1,st[dw]-1),Seg::query(ed[dw]+1,n));
		tmp2=Seg::query(st[y],ed[y]);

		if (tmp2>r){
			Seg::update(1,st[dw]-1,tmp2+t);
			Seg::update(ed[dw]+1,n,tmp2+t);
		}
		if (tmp1>r)
			Seg::update(st[y],ed[y],tmp1+t);
	}
	else{
		tmp1=Seg::query(st[x],ed[x]);
		tmp2=Seg::query(st[y],ed[y]);

		if (tmp2>r)
			Seg::update(st[x],ed[x],tmp2+t);
		if (tmp1>r)
			Seg::update(st[y],ed[y],tmp1+t);
	}
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
#endif
	int x,y,r,t;
	scanf("%d",&T);
	for (int o=1;o<=T;++o){
		scanf("%d%d%d",&n,&S,&P);
		memset(h,-1,sizeof(h));
		tot=0;
		for (int i=1;i<n;++i){
			scanf("%d%d",&x,&y);
			add(x,y); add(y,x);
		}
		dfn_t=0;
		dfs(0,1,1);
		Seg::build(n);
		scanf("%d",&m);
		for (int i=1;i<=m;++i){
			scanf("%d%d%d%d",&x,&y,&r,&t);
			modify(x,y,r,t);
		}
		printf("%lld
",Seg::mx[1]);
	}
}
原文地址:https://www.cnblogs.com/yoyoball/p/10145623.html