Educational Codeforces Round 64(Unrated for Div.1+Div. 2)

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

等hacking结束再订正EFG吧,先贴一下BD的代码,AC两个垃圾题就不写了。

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

口胡了一个做法,等hacking time结束再写。

FG

没来得及看

猜你喜欢

转载自www.cnblogs.com/hfctf0210/p/10801290.html
今日推荐