zoukankan      html  css  js  c++  java
  • 生哥的hu测

    今天的生哥hu测,都是思路题,代码不长,对于思维的提升很有帮助
    可惜没有全力去做。。。

    T1

    这里写图片描述

    分析:
    不用SG函数的一道博弈
    觉得xz的想法非常的好
    如果我们想要留下一个点的权值(假设为x)
    当且仅当这个点只有一条连边,这是我们就可以把这条边练连的其他点干掉
    游戏结束,如果我们不是在这种情况下进行了与x相连的边的删减
    这就会导致这个点的主动权到了另一个人手里
    因为两人的目的完全不同,所以对手一定会删掉x来逼近目的
    所以先手干脆在叶子上操作,一步结束游戏

    生哥的解释更为科学一些:
    假设说我们有一棵树是这样的:
    这里写图片描述

    tip

    叶子节点的找法 son[x]=0
    如果根节点(1)只有一个儿子,那ta也算是一种叶子结点

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int N=501;
    int n;
    struct node{
        int x,y,nxt;
    };
    node way[N<<1];
    int v[N];
    int st[N],tot=0;
    int son[N];
    
    void add(int u,int w)
    {
        tot++;
        way[tot].x=u;way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;
        tot++;
        way[tot].x=w;way[tot].y=u;way[tot].nxt=st[w];st[w]=tot;
    }
    
    void dfs(int x,int fa,int dep)
    {
        int i;
        for (int i=st[x];i;i=way[i].nxt)
            if (way[i].y!=fa)
                son[x]++,
                dfs(way[i].y,x,dep+1);
    }
    
    int main()
    {
        freopen("y.in","r",stdin);
        freopen("y.out","w",stdout);
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&v[i]);
        for (int i=1;i<n;i++)
        {
            int u,w;
            scanf("%d%d",&u,&w);
            add(u,w);
        }
        int ans=0;
        dfs(1,0,1);
        for (int j=1;j<=n;j++)
            if (son[j]==0)
                ans=max(ans,v[j]);   //叶子节点中的最大值
        if (son[1]==1) ans=max(ans,v[1]); 
        printf("%d",ans);
        return 0;
    }

    T2

    这里写图片描述
    这里写图片描述

    分析:
    好几个人表示是贪心
    记得TA爷说过:贪心千万不要证明,证明不出来的
    生哥:这个贪心你最好要证明一下

    在环上的走法,很明显只有3种
    这里写图片描述

    如果走法3用了两次
    假设第一次我们在左半边分发a个,右半边分发b个
    第二次我们在右半边分发c个,右半边分发d个
    则左半部分a+c,右半部分b+d
    这就导致有一部分是<=k
    (因为a+b+c+d=2*k)
    那我们还不如带足了k个只分给半边,这样的花费一定 <= 转两圈
    所以3
    操作只能使用一次

    同时显然,在转一圈的过程中,我们尽量给距离0远的点分发
    这样我们分发的一定是一个序列
    这样我们就可以枚举3操作时分发的区间
    剩下的区间可以贪心求处答案
    统计一个最小值就可以了

    我们把一个环通过0拆成一条直线
    f[i]表示发到i的最小花费

    T3

    这里写图片描述
    这里写图片描述

    分析:
    二分答案
    二分是一个很神奇的操作
    就相当于是一个水平线
    把所有数字分成了大于ta和小于ta两部分
    我们把这两部分用01编号
    这样原序列就变成了一个01序列

    接下来就可以dp了
    f[i][j]表示第i位是j需要多少1
    三位三位的转移
    这里写图片描述

    if (mid>=统计出来的答案) l=mid;

    else r=mid;

  • 相关阅读:
    commonjs promise/A 规范
    Java之抽象类
    Java中多态的用法
    Java之方法的重写
    Java中static的用法
    java中this的用法
    Java概述
    二叉排序树的创建、插入、删除
    常用排序算法
    LeetCode小白菜笔记[2]:Reverse Integer
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673385.html
Copyright © 2011-2022 走看看