• Full_of_Boys训练5总结


    题目来源:2017-2018 ACM-ICPC, NEERC, Moscow Subregional Contest

    A. Advertising Strategy

    贪心方法:把一部分k放到初始值,剩下一部分,等到最后用。然后,枚举第一部分放多少即可。

    #include <bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    ll n,k,ans=1000000000000000000LL;
    int main() {
        scanf("%lld %lld",&n,&k);
        if(n<=k) {
            puts("1");return 0;
        }
        for(int t=1;t<=k-1;++t) {
            ll a1=t,tt=1;
            a1 = a1 + min(a1, (n-a1)/2);
            while(a1 < n-k+t) {
                a1 = a1 + min(a1,(n-a1)/2);
                ++tt;
            }
            ++tt;
            ans = min(tt, ans);
        }
        printf("%lld
    ", ans);
        return 0;
    }

    C. Carpet

    先树剖,构造方法:把重儿子放到当前层的最右端,轻儿子放到下一层,第二次dfs注意顺序,否则会交叉。这样保证高度为logn。。。先是想到如果树低,可以一层层放,我觉得这种题,一种做法就是多手动构造几组解,然后找找规律。另一种思路,就是观察数据范围,20和100000,首先,第一个数很小,就考虑如何降低深度,于是想到了重心,可是感觉没啥用,再怎么调深度也不够,就得朝着把一些比较长的链拿出来,放到一排上这个思路做,那就先求直径,然后,把直径上的点放在第一排,对于这些点延伸出的子树,再求直径,从左到右放在,第二排,递归的再去放第三排,这样应该是有保证的吧,,,写出来wa了。。哎再改改。。然后树剖这个思路相对比较好写吧。。。手懒脑子差。。。只好膜题解。后期也有问题,擅自认怂了,三个人一起刚掉G。。。没有同时开题,现场一定要避免这种问题。还有些时候,A完签到题,就放松了。。。脑子停转的问题,还是很严重。

    update :好吧,那个每次求直径的贪心可以卡掉。。。树的长相如下,这可能只是树的一部分,即它的叶子节点也许会连和他类似的结构。显然如果不幸,每次都找到分叉最少的那条直径。树的深度,就没有保证了。。。所以,我们每次怎么算出一棵树中分叉最多的直径呀?bfs的时候处理一下度数和最大的路径?然而还是wa。。。到这好像再想不到树剖就太zz了,保证重链数上界logn条。。。这么优秀的做法。

    update:又想了想。。。我每次保证当前这棵树的重心在这一层,选出过重心的最长径or度数和最大路径。。。可以吗???

    发现构造题,有些布星啊。有时间多学点组合构造玩。。。

    #include <bits/stdc++.h>
    const int maxn = 1e5 + 7;
    using namespace std;
    struct edge{int e,nxt;}E[maxn<<1];
    int h[maxn],cc;
    void add(int u,int v){
        E[cc].e=v;E[cc].nxt=h[u];h[u]=cc;++cc;
    }
    int sz[maxn], fa[maxn], son[maxn];
    void dfs1(int u,int pre){
        sz[u]=1;
        fa[u]=pre;
        for(int i=h[u];~i;i=E[i].nxt){
            int v=E[i].e;
            if(v!=pre){
                dfs1(v,u);
                sz[u]+=sz[v];
                if(son[u]==-1||sz[v]>sz[son[u]])
                    son[u]=v;
            }
        }
    }
    int X[maxn],Y[maxn],cnt[55];
    void dfs2(int u, int d){
        X[u]=++cnt[d];Y[u]=d;
        for(int i=h[u];~i;i=E[i].nxt){
            int v=E[i].e;
            if(v!=son[u]&&v!=fa[u])dfs2(v,d+1);
        }
        if(son[u]==-1)return;
        dfs2(son[u],d);
    }
    int n,x,y;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)h[i]=son[i]=-1;
        for(int i=1;i<n;++i)scanf("%d%d",&x,&y),add(x,y),add(y,x);
        dfs1(1,0);
        dfs2(1,1);
        for(int i=1;i<=n;++i)cout << X[i] <<' '<<Y[i]<<'
    ';
        return 0;
    }

    D. Decoding of Varints

    卡unsigned long long。。。注意运算过程

    G. God of Winds 

    设第一个位置的值为0,然后可以通过递推,求出整张图每个位置的值。check一下,是否矛盾即可。WA点:爆int!!!!这道题,一个难点就是考读题。。。读懂之后,想到把整个图每个位置设成未知数,求解方程,显然会tle。然后,觉得是不每行都能解方程??oldz推了一下,说方程解不了,有一个未知数。反应了半天。其实就是有一个自由项。那我随便设它是什么就行了。然后就可以通过,格子之间的关系推出整张图辣。以后,再也不用int了。。。

    H. Hilarious Cooking

    发现一定可以构成连续的一段T,那么考虑如何计算出最大值,最小值,再判断一下,是否在区间内就行了。显然,如果只有两端给定,一段区间的最值只受两端影响。那么,分别计算每段的最值加起来就行。注意还有两头要考虑。然后,每段的最值,就可以堆一推公式,o(1)计算了。嘴完了。(感觉挺简单的啊。。除了讨论那块比较麻烦,为啥就没读这题。。不能盲目跟榜哇

  • 相关阅读:
    【leetcode】Sum Root to Leaf Numbers(hard)
    【leetcode】First Missing Positive(hard) ☆
    【leetcode】Next Permutation(middle)
    【好玩的应用】QQ连连看辅助工具
    【leetcode】Binary Tree Preorder Traversal (middle)★
    【leetcode】Reverse Words in a String(hard)☆
    【leetcode】Same Tree(easy)
    【leetcode】Factorial Trailing Zeroes(easy)
    【leetcode】Maximum Gap(hard)★
    Behavioral模式之Chain of Responsibility模式
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/9038908.html
Copyright © 2020-2023  润新知