zoukankan      html  css  js  c++  java
  • BZOJ 4446: [Scoi2015]小凸玩密室

    二次联通门 : BZOJ 4446: [Scoi2015]小凸玩密室

    /*
        BZOJ 4446: [Scoi2015]小凸玩密室
    
        树形dp
    
        做到这么正常的题突然感觉好不适应。。。。
        
        考虑转移
        f[x][y] 表示从x点转移到y点的代价
        则我们需要处理出以x为根的子树的代价
        讨论处理一下即可(有没有左儿子,有没有右儿子,或是都有)
    
        但是这样转移是O(N^2)的
    
        所以我们考虑优化
        显然有很多转移是不需要的
        比如y在x的子树中时就没必要转移
    
        那么考虑优化
        设g[x][i]表示走完x的子树再走到x的深度为i的祖先的最小代价
        那么在讨论一下处理就好(看代码里的方程应该很好理解)
        
        统计时就是枚举点,统计父亲,兄弟, 然后父亲的父亲,兄弟。。
        更新答案即可
    */
    #include <cstdio>
    #include <iostream>
    
    const int BUF = 12312312;
    char Buf[BUF], *buf = Buf;
    
    typedef long long LL;
    using std :: min;
    inline void read (int &now)
    {
        for (now = 0; !isdigit (*buf); ++ buf);
        for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf);
    }
    
    #define Max 200010
    LL f[Max][Max / 10000], g[Max][Max / 10000];
    LL deep[Max], d[Max];
    int key[Max];
    int v[Max];
    
    int Main ()
    {
        fread (buf, 1, BUF, stdin); 
        int N, z; read (N); register int i, j;
        for (i = 1; i <= N; ++ i)
            read (key[i]);
        for (i = 2, deep[1] = 1; i <= N; ++ i)
        {
            read (z), d[i] = d[i >> 1] + z;
            deep[i] = deep[i >> 1] + 1, v[i] = z;
        }
        LL l, r, y; register LL x; LL res;
        for (x = N; x; -- x)
            for (i = 0; i < deep[x]; ++ i)
            {
                l = x << 1, r = l | 1;
                y = (x >> (deep[x] - i - 1)) ^ 1;
                if (l > N) 
                    f[x][i] = key[y] * (d[x] + d[y] - (d[y >> 1] << 1));
                else if (r > N)
                    f[x][i] = key[l] * v[l] + f[l][i];
                else 
                    f[x][i] = min (key[l] * v[l] + f[r][i] + f[l][deep[x]], key[r] * v[r] + f[l][i] + f[r][deep[x]]);
            }
        for (x = N; x; -- x)
            for (i = 0; i <= deep[x]; ++ i)
            {
                l = x << 1, r = l | 1;
                y = x >> (deep[x] - i);
                if (l > N)
                    g[x][i] = key[y] * (d[x] - d[y]);
                else if (r > N)
                    g[x][i] = g[l][i] + key[l] * v[l];
                else 
                    g[x][i] = min (key[l] * v[l] + f[l][deep[l] - 1] + g[r][i], key[r] * v[r] + f[r][deep[r] - 1] + g[l][i]);
            }
        LL Answer = g[1][0]; LL pos;
        for (i = 2; i <= N; ++ i) 
        {
            res = g[i][deep[i] - 1], pos = i;
            for (; pos != 1; pos >>= 1)
            {
                y = pos ^ 1, z = pos >> 1;
                if (y > N) res += key[z >> 1] * v[z];
                else res += key[y] * v[y] + g[y][deep[z] - 1];
            }
            Answer = min (Answer, res);
        }
        printf ("%lld", Answer);
        return 0;
    }
    int ZlycerQan = Main ();
    int main (int argc, char *argv[]) {;}
  • 相关阅读:
    TensorFlow中的基本概念
    理解 tf.Variable、tf.get_variable以及范围命名方法tf.variable_scope、tf.name_scope
    深度神经网络关键词解释
    [python] os.path.join() 与 sys.path
    Git 遇到的坑
    [转] 资深程序员得到的职场经验教训
    VS CODE 快捷键
    解决VS Code使用code runner开发Python乱码问题
    熵,条件熵,互信息,交叉熵
    Visual Studio Code 支持TensorFlow配置支持
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/7422163.html
Copyright © 2011-2022 走看看