【CC】Batman and Tree

Portal --> CC Batman and Treeios

Solution

  一開始看到很懵。。感受無從下手(由於本身太菜了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

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("\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]);
    }
}
相關文章
相關標籤/搜索