zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 64(Unrated for Div.1+Div. 2)

    什么垃圾比赛,A题说的什么鬼楞是没看懂。就我只会BD(其实C是个大水题二分),垃圾游戏,技不如人,肝败吓疯,告辞,口胡了E就睡觉了。

    B

    很容易发现,存在一种方案,使得相同字母连在一起,然后发现,当字母出现种类数大于等于4时,可以奇偶性相间地连接,然后讨论种类数<=3的:种类数为1,显然直接输出;种类数为2,若两字母相邻则无解,否则直接输出;种类数为3,若三字母相邻则无解,否则按照213/231(至少一种符合条件)输出。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=107;
    int T,n,m,ans,sum[N],id[N];
    char s[N];
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",s+1),n=strlen(s+1);
            memset(sum,0,sizeof sum);
            memset(id,0,sizeof id);
            for(int i=1;i<=n;i++)sum[s[i]-'a'+1]++;
            int num=0;
            for(int i=1;i<=26;i++)if(sum[i])id[i]=++num;
            if(num==1)
            {
                for(int i=1;i<=n;i++)printf("%c",s[i]);
            }
            else if(num>=4)
            {
                for(int i=26;i>=1;i--)
                if(id[i]&1)
                {
                    for(int j=1;j<=sum[i];j++)printf("%c",'a'+i-1);
                }
                for(int i=26;i>=1;i--)
                if(id[i]&&id[i]%2==0)
                {
                    for(int j=1;j<=sum[i];j++)printf("%c",'a'+i-1);
                }
            }
            else if(num==3)
            {
                int flag=0;
                for(int i=2;i<=25;i++)if(sum[i]&&sum[i-1]&&sum[i+1])flag=1;
                if(flag)printf("No answer");
                else{
                    for(int i=2;i<=25;i++)
                    for(int j=1;j<i;j++)
                    for(int k=i+1;k<=26;k++)
                    if(sum[j]&&sum[i]&&sum[k])
                    {
                        for(int t=1;t<=sum[i];t++)printf("%c",'a'+i-1);
                        if(j==i-1)
                        {
                            for(int t=1;t<=sum[k];t++)printf("%c",'a'+k-1);
                            for(int t=1;t<=sum[j];t++)printf("%c",'a'+j-1);
                        }
                        else{
                            for(int t=1;t<=sum[j];t++)printf("%c",'a'+j-1);
                            for(int t=1;t<=sum[k];t++)printf("%c",'a'+k-1);
                        }
                    }
                }
            }
            else{
                int flag=0;
                for(int i=1;i<=25;i++)if(sum[i]&&sum[i+1])flag=1;
                if(flag)printf("No answer");
                else{
                    for(int i=1;i<=26;i++)if(sum[i])
                    {
                        for(int j=1;j<=sum[i];j++)printf("%c",'a'+i-1);
                    }
                }
            }
            puts("");
        }
    }
    View Code

    D

    很容易想到一个DP,令f[i]表示以i为根的子树,从下面的节点走上来,最后一步是黑边的点数,g[i]表示全走白边的点数,于是就有f[u]=Σ(f[son]+g[son]+1),son为经过黑边的son,g[u]=Σ(g[son]+1),son为经过白边的son。然后这个东西很容易换根DP,根据黑白边讨论一下即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2e5+7;
    int n,cnt,f[N],g[N],nf[N],ng[N],hd[N],v[N<<1],nxt[N<<1],w[N<<1];
    ll ans;
    void adde(int x,int y,int z){v[++cnt]=y,nxt[cnt]=hd[x],w[cnt]=z,hd[x]=cnt;}
    void dfs(int u,int fa)
    {
        for(int i=hd[u];i;i=nxt[i])
        if(v[i]!=fa)
        {
            dfs(v[i],u);
            if(!w[i])g[u]+=g[v[i]]+1;
            else f[u]+=f[v[i]]+g[v[i]]+1;
        }
    }
    void dfs2(int u,int fa)
    {
        ans+=nf[u]+ng[u];
        for(int i=hd[u];i;i=nxt[i])
        if(v[i]!=fa)
        {
            if(!w[i])nf[v[i]]=f[v[i]],ng[v[i]]=ng[u];
            else nf[v[i]]=nf[u]-g[v[i]]+ng[u],ng[v[i]]=g[v[i]];
            dfs2(v[i],u);
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1,x,y,z;i<n;i++)scanf("%d%d%d",&x,&y,&z),adde(x,y,z),adde(y,x,z);
        dfs(1,0);
        nf[1]=f[1],ng[1]=g[1],dfs2(1,0);
        cout<<ans;
    }
    View Code

    E

    口胡了一个分治做法,一写发现,它居然过了。感觉本题比D简单。

    做法大致如下:直接算很难处理,考虑分治,对于长度大于等于3的区间[l,r],考虑覆盖mid和mid+1的所有区间,可以把[l,r]分为[l,mid]和[mid+1,r]两半,然后mx[i]对于左半部分表示后缀最大值,对于右半部分表示前缀最大值,然后枚举位置计算另一端的位置是否符合题意,因为区间的max值出现在两端的mx之一,所以左右都搜一下即可统计所有答案。复杂度O(nlogn)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2e5+7;
    int n,ans,a[N],b[N],mx[N];
    void solve(int l,int r)
    {
        if(l+1>=r)return;
        int mid=l+r>>1;
        solve(l,mid),solve(mid+1,r);
        mx[mid]=a[mid];for(int i=mid-1;i>=l;i--)mx[i]=max(mx[i+1],a[i]);
        mx[mid+1]=a[mid+1];for(int i=mid+2;i<=r;i++)mx[i]=max(mx[i-1],a[i]);
        for(int i=l;i<=mid;i++)
        {
            int pos=b[mx[i]-a[i]];
            if(pos>mid&&pos<=r&&mx[pos]<mx[i])ans++;
        }
        for(int i=mid+1;i<=r;i++)
        {
            int pos=b[mx[i]-a[i]];
            if(pos>=l&&pos<=mid&&mx[pos]<mx[i])ans++;
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[a[i]]=i;
        solve(1,n);
        printf("%d",ans);
    }
    View Code

    F

    很容易想到dp,令f[i][j]表示第i轮当前卡为j且游戏继续的概率,然后根据第i轮每张卡有1/(n-i+1)的概率选中,直接写个前缀和,根据题意暴力DP转移即可,代码20行。

    感觉这题更简单,CF这场什么垃圾排题顺序,难怪Unrated

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5005,mod=998244353;
    int n,ans,a[N],s[N],inv[N],f[N][N];
    int main()
    {
        scanf("%d",&n);
        for(int i=1,x;i<=n;i++)scanf("%d",&x),a[x]++;
        for(int i=n;i;i--)s[i]=s[i+1]+a[i];
        inv[1]=1;for(int i=2;i<=n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
        for(int i=1;i<=n;i++)f[1][i]=1ll*a[i]*inv[n]%mod;
        for(int i=2;i<=n;i++)
        for(int j=1,sum=0;j<=n;j++)
        f[i][j]=1ll*a[j]*sum%mod,sum=(sum+1ll*f[i-1][j]*inv[n-i+1])%mod;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        if(a[j]>1)ans=(ans+1ll*f[i][j]%mod*(a[j]-1)%mod*inv[n-i])%mod;
        printf("%d",ans);
    }
    View Code

    G

    看了下是个没有意思的大模拟,不想写也不会写,咕了。

    感觉真实难度顺序:C<B<E<D=F<G<A

  • 相关阅读:
    华为上机:IP地址转换
    华为上机:统计给定的两个数之间的素数的个数
    华为上机:五子棋
    华为上机:树的遍历
    华为上机:Tom的生日礼物
    华为上机:求2的N次幂的值
    2016搜狗:矩阵元素相乘
    欢迎使用CSDN-markdown编辑器
    lintcode:最大间隔
    lintcode:删除链表中指定元素
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10801290.html
Copyright © 2011-2022 走看看