• Bzoj2286--Sdoi2011消耗战


    栈模拟dfs,学到了新姿势

    这种题很显然应该用虚树去搞,之前也没写过虚树

    具体来说就是先维护dfs序,之后每次询问按dfs序排序后一个一个压入栈内,相当于dfs中的进入递归

    如果当前压入栈中的元素与之前栈顶元素的Lca深度小于栈顶元素,那么就把栈顶元素弹出,相当于dfs中的返回

    虚树上就很好dp了,在模拟dfs时就可以完成dp

    代码 :

    #include<bits/stdc++.h>
    #define LL long long 
    #define low(x) (x&(-x))
    #define LNF 1000000000000000
    using namespace std;
    inline int _max(int a,int b) {return a>b?a:b;}
    inline LL _min(LL a,LL b) {return a<b?a:b;}
    
    #define MAXN 250005
    #define MAXM 500005
    
    int n,m,k,q[MAXN];LL ans;
    int st[MAXN],top;
    
    int head[MAXN],cnt;
    struct Edge{
        int to,next,w;
    }e[MAXM];
    inline void insert(int a,int b,int c) {
        e[++cnt].next=head[a];head[a]=cnt;e[cnt].to=b;e[cnt].w=c;
        e[++cnt].next=head[b];head[b]=cnt;e[cnt].to=a;e[cnt].w=c;
    }
    
    int dep[MAXN],bz[MAXN][22],mi[MAXN][22],ds[MAXN],ind;
    void dfs(int v,int fr) {
        ds[v]=++ind;dep[v]=dep[fr]+1;bz[v][0]=fr;
        for(int i=head[v];i;i=e[i].next) 
            if(!ds[e[i].to]) {
                mi[e[i].to][0]=e[i].w;
                dfs(e[i].to,v);
            }
    }
    
    inline bool cmp(int a,int b) {return ds[a]<ds[b];}
    
    int Lca(int a,int b) {
        if(dep[a]<dep[b]) swap(a,b);
        for(int i=20;~i;i--) if(dep[bz[a][i]]>=dep[b]) a=bz[a][i];
        for(int i=20;~i;i--) if(bz[a][i]!=bz[b][i]) a=bz[a][i],b=bz[b][i];
        return a==b?a:bz[a][0];
    }
    
    LL dis(int a,int b) {
        LL ret=LNF;
        for(int i=20;~i;i--) if(dep[bz[a][i]]>=dep[b]) 
            ret=_min(ret,mi[a][i]),a=bz[a][i];
        return ret;
    }
    
    LL dp[MAXN];bool g[MAXN];
    void solve() {
        st[++top]=1;
        for(int i=1;i<=k;i++) g[q[i]]=1;
        for(int now,t,i=1;i<=k;i++) {
            now=q[i];t=Lca(now,st[top]);
            while(dep[t]<dep[st[top]]) {
                if(dep[st[top-1]]<=dep[t]) {
                    dp[t]+=_min(g[st[top]]?LNF:dp[st[top]],dis(st[top],t));
                    g[st[top]]=dp[st[top]]=0;top--;
                    if(st[top]!=t) st[++top]=t;
                    break;
                }
                else {
                    dp[st[top-1]]+=_min(g[st[top]]?LNF:dp[st[top]],dis(st[top],st[top-1]));
                    g[st[top]]=dp[st[top]]=0;top--;
                }
            }
            if(st[top]!=now) st[++top]=now;
        }
        while(top>1) {
            dp[st[top-1]]+=_min(g[st[top]]?LNF:dp[st[top]],dis(st[top],st[top-1]));
            dp[st[top]]=g[st[top]]=0;top--;
        }
        printf("%lld
    ",dp[top--]);dp[1]=0;
    }
    
    int main() {
        scanf("%d",&n);
        for(int a,b,c,i=1;i<n;i++) {
            scanf("%d%d%d",&a,&b,&c);
            insert(a,b,c);
        }
        memset(mi,0x3f3f,sizeof(mi));
        dfs(1,0);
        for(int i=1;i<=20;i++) for(int j=1;j<=n;j++) 
            bz[j][i]=bz[bz[j][i-1]][i-1],mi[j][i]=_min(mi[j][i-1],mi[bz[j][i-1]][i-1]);
        scanf("%d",&m);
        while(m--) {
            scanf("%d",&k);ans=0;
            for(int i=1;i<=k;i++) scanf("%d",&q[i]);
            sort(q+1,q+k+1,cmp);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    Thinkphp的 is null 查询条件是什么,以及exp表达式如何使用
    thinkphp5多文件上传如何实现
    如何动态改变audio的播放的src
    js插件---10个免费开源的JS音乐播放器插件
    html5页面怎么播放音频和视频
    Thinkphp5图片上传正常,音频和视频上传失败的原因及解决
    leetcode
    HTML5 画一张图
    Linux内核和根文件系统引导加载程序
    [dp] hdu 4472 Count
  • 原文地址:https://www.cnblogs.com/ihopenot/p/5983380.html
Copyright © 2020-2023  润新知