zoukankan      html  css  js  c++  java
  • BZOJ 3611: [Heoi2014]大工程 [虚树 DP]

    传送门

    题意:

    多次询问,求最长链最短链链总长


    煞笔$DP$记录$d,c,f,g$

    $MD$该死拍了一下午没问题然后交上去就$T$

    然后发现树链剖分写成$size[v]+=size[u]$

    我想知道我随机生成的大数据是怎么跑过去的!!!!!!!!

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e6+5,INF=1e9;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n,Q;
    struct Edge{
        int v,ne,w;
    }e[N<<1];
    int cnt,h[N];
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    int deep[N];
    inline void ins2(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        e[cnt].w=deep[v]-deep[u];
    }
    
    int dfn[N],dfc,top[N],size[N],mx[N],fa[N];
    void dfs(int u){
        size[u]++;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v==fa[u]) continue;
            fa[v]=u;deep[v]=deep[u]+1;
            dfs(v);
            size[u]+=size[v];
            if(size[v]>size[mx[u]]) mx[u]=v;
        }
    }
    void dfs2(int u,int anc){
        dfn[u]=++dfc; top[u]=anc;
        if(mx[u]) dfs2(mx[u],anc);
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].v!=fa[u] && e[i].v!=mx[u]) dfs2(e[i].v,e[i].v);
    }
    inline int lca(int x,int y){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            x=fa[top[x]];
        }
        return deep[x]<deep[y] ? x : y;
    }
    
    int key[N],c[N],f[N],g[N];
    ll d[N],Sum;
    int Max,Min;
    void dp(int u){//printf("dp %d
    ",u);
        d[u]=0;
        if(key[u]) c[u]=1,f[u]=g[u]=0;
        else c[u]=0,f[u]=-INF,g[u]=INF;
    
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v,w=e[i].w;
            dp(v);
            Sum+=d[u]*c[v]+c[u]*(d[v]+(ll)c[v]*w);
            Max=max(Max,f[u]+f[v]+w);
            Min=min(Min,g[u]+g[v]+w);
    
            d[u]+=d[v]+c[v]*w;
            c[u]+=c[v];
            f[u]=max(f[u],f[v]+w);
            g[u]=min(g[u],g[v]+w);
        }
        h[u]=0;
    }
    int a[N];
    inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
    int st[N];
    void solve(){
        cnt=0;
        int n=read();//printf("n %d
    ",n);
        for(int i=1;i<=n;i++) a[i]=read(),key[a[i]]=1;
        sort(a+1,a+1+n,cmp);
        int top=0;
        for(int i=1;i<=n;i++){
            if(!top) {st[++top]=a[i];continue;}
            int x=a[i],f=lca(x,st[top]);
            while(dfn[f]<dfn[st[top]]){
                if(dfn[f]>=dfn[st[top-1]]){
                    ins2(f,st[top--]);
                    if(f!=st[top]) st[++top]=f;
                    break;
                }else ins2(st[top-1],st[top]),top--;
            }
            st[++top]=x;
        }
        while(top>1) ins2(st[top-1],st[top]),top--;
        Sum=0;Max=-INF;Min=INF;
        dp(st[1]);
        for(int i=1;i<=n;i++) key[a[i]]=0;
        printf("%lld %d %d
    ",Sum,Min,Max);
    }
    int main(){
        freopen("in","r",stdin);
        n=read();
        for(int i=1;i<n;i++) ins(read(),read());
        dfs(1);dfs2(1,1);
        memset(h,0,sizeof(h));
        Q=read();
        while(Q--) solve();
    }
  • 相关阅读:
    浅拷贝在项目中的应用
    MVC3中使用AuthorizeAttribute特性来完成登陆权限的验证
    一个面向对象的JS例子,很好的支持了开闭原则(不要重复你昨天的代码)
    c++学习笔记5
    JS跨域访问操作iframe
    Select函数
    MacOS10.8.3+Xcode4.6+IOS6.1 编译FFmpeg,简单使用
    eclipse部署,在tomcat中找不到eclipse发布的项目。eclipse更改项目发布路径
    初识Volley(二)
    MySQL 5.0 迁移到 MariaDB 10.0.2 存储过程无法迁移
  • 原文地址:https://www.cnblogs.com/candy99/p/6526913.html
Copyright © 2011-2022 走看看