ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF训练

2020-01-18 19:00:57  阅读:198  来源: 互联网

标签:训练 int CF long str isdigit include getchar


CF 612 div1

三道大水题

A

题解

dp,用 $ f[i][j][0/1]$ 表示到第 \(i\) 个空格且一共填了 \(j\) 个奇数,末尾为奇数或偶数的最小值

转移见代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int read()
{
    int k=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) k=k*10+c-'0';return k*f;
}
int n,x,y,a[500],f[105][105][2];
int tot,pos[500];
int main()
{
    n=read();
    y=n/2;x=n-y;
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        if(a[i]&1) x--;
        else if(a[i]!=0) y--;
        else pos[++tot]=i;
    }
    memset(f,0x3f,sizeof(f));
    if(pos[1]==1)
    {
        f[1][1][1]=f[1][0][0]=0;
    }
    else 
    {
        f[1][1][1]=(a[pos[1]-1]&1)^1;
        f[1][0][0]=(a[pos[1]-1])&1;
    }
    for(int i=2;i<=tot;i++)
        for(int j=0;j<=x&&j<=i;j++)
        {
            if(pos[i]-1!=pos[i-1])
            {
                f[i][j][0]=min(f[i-1][j][0]+(a[pos[i-1]+1]&1),f[i-1][j][1]+((a[pos[i-1]+1]&1)^1))+(a[pos[i]-1]&1);
                if(j) f[i][j][1]=min(f[i-1][j-1][0]+(a[pos[i-1]+1]&1),f[i-1][j-1][1]+((a[pos[i-1]+1]&1)^1))+((a[pos[i]-1]&1)^1);
            }
            else 
            {
                f[i][j][0]=min(f[i-1][j][0],f[i-1][j][1]+1);
                if(j) f[i][j][1]=min(f[i-1][j-1][1],f[i-1][j-1][0]+1);
            }
        }
    if(pos[tot]!=n) 
    {
        f[tot][x][1]+=(a[pos[tot]+1]&1)^1;
        f[tot][x][0]+=a[pos[tot]+1]&1;
    }
    int ans=min(f[tot][x][0],f[tot][x][1]);
    if(!tot) ans=0;
    for(int i=1;i<n;i++)
        if(a[i]!=0&&a[i+1]!=0)
            ans+=((a[i]&1)^(a[i+1]&1));
    printf("%d\n",ans);
    return 0;
}

B

题解

从叶子向根部确定值即可,如果某节点的 \(c[i]\) 大于它所有子树的节点,就输出 NO。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int read()
{
    int k=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) k=k*10+c-'0';return k*f;
}
const int N=5005;
int n,m,sum,a[N],b[N],c[N];
int tot,to[N],nextt[N],head[N];
bool cmp(int x,int y)
{
    return a[x]<a[y];
}
void add(int a,int b)
{
    to[++tot]=b;
    nextt[tot]=head[a];
    head[a]=tot;
}
void get(int u)
{
    b[++sum]=u;
    for(int i=head[u];i;i=nextt[i])
        get(to[i]);
}
void dfs(int u)
{
    for(int i=head[u];i;i=nextt[i])
        dfs(to[i]);
    sum=0;
    for(int i=head[u];i;i=nextt[i])
    {
        get(to[i]);
    }
    if(c[u]>sum) {puts("NO");exit(0);}
    if(!head[u])
    {
        m++;
        a[u]=m*N+1;
        return;
    }
    sort(b+1,b+1+sum,cmp);
    if(c[u]==0)
        a[u]=a[b[1]]-1;
    else if(a[b[c[u]+1]]-a[b[c[u]]]>1||c[u]==sum)
        a[u]=a[b[c[u]]]+1;
    else 
    {
        a[u]=a[b[c[u]]]+1;
        for(int i=c[u]+1;i<=sum;i++)
            a[b[i]]++;
    }
}
int main()
{
    int x,rt;
    n=read();
    for(int i=1;i<=n;i++)
    {
        x=read();
        if(x) add(x,i);
        else rt=i;
        c[i]=read();
    }
    dfs(rt);
    puts("YES");
    for(int i=1;i<=n;i++)
        printf("%d\n",a[i]);
    return 0;
}

C

题解

求 \(s[1...n]\) 和 \(s[2...n]\) 的所有字串,多出来的 \(n\) 个字串就是 \(s[1..i](1≤i≤n)\) ,我们很容易就求出原字符串了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#define ll long long
using namespace std;
int read()
{
    int k=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) k=k*10+c-'0';return k*f;
}
const int N=205;
int n,a[26],b[26];
string str,ss[N];
char ans[N];
multiset<string> s;
bool cmp(string a,string b)
{
    return a.size()<b.size();
} 
int main()
{
    cin>>n;
    if(n==1)
    {
        cout<<"? 1 1\n";
        fflush(stdout);
        cin>>ans[1];
        cout<<"! "<<ans[1]<<endl;
        fflush(stdout);
        return 0;
    }
    else 
    {
        cout<<"? 1 "<<n<<endl;
        fflush(stdout);
        for(int i=1;i<=n*(n+1)/2;i++)
        {
            cin>>str;
            sort(str.begin(),str.end());
            s.insert(str);
        }
        cout<<"? 2 "<<n<<endl;
        fflush(stdout);
        for(int i=1;i<=n*(n-1)/2;i++)
        {
            cin>>str;
            sort(str.begin(),str.end());
            s.erase(s.find(str));
        }
        n=0;
        for(multiset<string>::iterator i=s.begin();i!=s.end();i++)
            ss[++n]=*i;
        sort(ss+1,ss+1+n,cmp);
        for(int i=1;i<=n;i++)
        {
            memset(a,0,sizeof(a));
            for(int j=0;j<ss[i].size();j++)
                a[ss[i][j]-'a']++;
            for(int j=0;j<26;j++)
                if(a[j]-b[j]) 
                    ans[i]='a'+j;
            memcpy(b,a,sizeof(a));
        }
        cout<<"! "<<ans+1<<endl;
        fflush(stdout);
        return 0;
    }
}

标签:训练,int,CF,long,str,isdigit,include,getchar
来源: https://www.cnblogs.com/waing/p/12209884.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有