CF训练
Posted waing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF训练相关的知识,希望对你有一定的参考价值。
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
",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
",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
";
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;
}
}
以上是关于CF训练的主要内容,如果未能解决你的问题,请参考以下文章