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$。

没什么水平。。。

原文地址:https://www.cnblogs.com/Milk-Feng/p/11345142.html