Portal --> CC Batman and Treeios
一開始看到很懵。。感受無從下手(由於本身太菜了qwq)c++
膜拜了題解以後發現好像並無想象的那麼複雜qwqui
其實冷靜下來考慮dp,用\(f[i]\)表示當前在\(i\)的最大能量值,而後對於一個從\(x\)到\(y\)的強盜,考慮找一條路徑知足\(x\)到\(y\)的簡單路徑是其子路徑,那麼咱們就能夠用知足條件的路徑的端點\(f\)值的最大值來更新走到的另外一個端點處的新\(f\)值spa
將dfs序處理出來,不難發現知足條件的路徑的端點對應的應該是幾段區間,具體一點就是(默認\(dep[x]<=dep[y]\)):debug
(1)\(x\)是\(y\)的祖先,此時記\(dw\)爲知足\(y\in subtree(dw)\)且\(dw\in son(x)\)的節點,那麼能夠選路徑的的端點應該一個在區間\([1,st[dw]]\cup[ed[dw]+1,n]\)內,一個在\([st[y],ed[y]]\)內code
(2)\(x\)不是\(y\)的祖先,那麼此時能夠選路徑的端點應該一個在\([st[x],ed[x]]\),一個在\([st[y],ed[y]]\)內get
那麼直接線段樹維護一下就行了,實現一個區間取max和區間查詢max便可(吉老師線段樹)
string
#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("\n"); } 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\n",Seg::mx[1]); } }