• 2019-8-13 考试总结


    A. count

    在我看来不是个水题。。

    想了好长时间,想到和正解差不多的思路,

    本质应该是个贪心。

    每次递归求每个节点的$size$,如果这个节点的$size$是现在枚举的每块的大小$L$,那么它的$size$置为$0$,

    看一下到根节点的时候$size$是否为$0$。

    思路应该是对的。

    正解要好一点,看一下有多少节点的$size$可以整除$L$,如果这个数大于等于$frac{n}{L}$,则$ans++$。

    丑陋的代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #define Reg register
    #define Maxn 1000050
    using namespace std;
    int n,tot,ans,top,anp,now,siz[Maxn],fir[Maxn],vis[Maxn],num[Maxn];
    struct Tu {int st,ed,next;} lian[Maxn*2];
    void add(int x,int y)
    {
        lian[++tot].st=x;
        lian[tot].ed=y;
        lian[tot].next=fir[x];
        fir[x]=tot;
        return;
    }
    void dfs(int x,int fa)
    {
        siz[x]=1;
        for(Reg int i=fir[x];i;i=lian[i].next)
        {
            if(lian[i].ed==fa) continue;
            dfs(lian[i].ed,x);
            siz[x]+=siz[lian[i].ed];
        }
        ++num[siz[x]];
        return;
    }
    int main()
    {
        scanf("%d",&n);
        for(Reg int i=1,x,y;i<=n-1;++i)
        {
            scanf("%d%d",&x,&y);
            add(x,y); add(y,x);
        }
        dfs(1,0);
        for(Reg int i=n;i>=1;--i)
        {
            if(n%i!=0) continue;
            int p=0;
            for(Reg int j=1;i*j<=n;++j) p+=num[i*j];
            if(p>=n/i) ++ans;
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    B. Dinner

    好吧,它是个圆桌。。

    上来看完$T1$没啥思路然后滚来看$T2$,乍一看二分答案水题。。

    结果我就$WA0$了。

    还要枚举一个起点,暴力的话时间复杂度$O(n^2logn)$。

    承受不住。

    根据$starsing$大神的推导,只要枚举$1$号点可以一次到达的点即可。

    因为如果把这个点之后的点当作起点,就相当于把它作为中间的断点,把$1$能到达的某个点当作起点,因为是个圆桌。

    丑陋的代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define Maxn 50050
    #define Reg register
    #define INF 0x7ffffff
    #define int long long
    #define _min(x,y) ((x)<(y)?(x):(y))
    #define _max(x,y) ((x)>(y)?(x):(y))
    #define _abs(x) ((x)<0?(-1*(x)):(x))
    using namespace std;
    int n,m,mxx,mnn,T[Maxn*2],sum[Maxn*2],nxt[Maxn*2][20],vis[Maxn*2];
    bool judge(int t)
    {
        int p=1;
        while(p+1<=2*n&&sum[p+1]-sum[1]<=t) ++p;
        for(Reg int s=1;s<=p;++s)
        {
            int p=0,now=s;
            for(Reg int i=1;i<=m;++i)
                now=upper_bound(sum+i,sum+n*2+1,sum[now]+t)-sum-1;
            if(now>=s+n) return 1;
        }
        return 0;
    }
    int erfen(int l,int r)
    {
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(judge(mid)) return erfen(l,mid);
        else return erfen(mid+1,r);
    }
    signed main()
    {
        scanf("%lld%lld",&n,&m);
        for(Reg int i=1;i<=n;++i)
        {
            scanf("%lld",&T[i]);
            sum[i]=sum[i-1]+T[i];
            mxx+=T[i];
            mnn=_max(mnn,T[i]);
        }
        for(Reg int i=n+1;i<=n*2;++i)
        {
            T[i]=T[i-n];
            sum[i]=sum[i-1]+T[i];
        }
        if(m>=n) printf("%lld
    ",mnn);
        else
        {
            int ans=erfen(mnn,mxx);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    C. chess

    总结:

    怎么说呢,考试一次高一次低,起伏有点大。。

    可能是我太菜了。。。

    总体来说没上次考得好,主要是$T2$。

    当时审题可能有问题,而且非常想当然,以为完全能过这道题。。

    样例$2$: $4$ $2$     $1$ $2$ $3$ $4$。

    输出: $5$

    样例$2$错误解释:

    把第三个人分开,分成一个$1$和一个$2$。

    然后左边就成了$1+2+2=5$,右边也是$1+4=5$。

    正确解释:

    从第二个人开始,然后$2+3=5$,$4+1=5$。

    审题仔细,不要想当然。

    心态的话,应该还不错。

    最后$60+0+30=90$。

    没什么水平。。。

  • 相关阅读:
    015.现场.快用Scala(4月)
    014.科普.有生产力的Sql语句
    JQuery速记
    草稿
    使用jquery.layout.js构建页眉/页脚/左侧导航/中间展示内容的网页结构
    实践自己的WebSite______流水
    如何生成带注释的DLL文件
    MVC如何在解决方案下创建文件夹
    如何利用子视图
    【草稿】JS中如何操作时间
  • 原文地址:https://www.cnblogs.com/Milk-Feng/p/11345142.html
Copyright © 2020-2023  润新知