Codeforces Round #660 (Div. 2)

A. Captain Flint and Crew Recruitment

题解

一般情况下是6,10,14,n-30都能满足,但是注意题中说要四个数互不相同,所以还得考虑当n-30=6,10,14的时候再自己构造一下。

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
	return x*f;
}
int T,n;
int main()
{
	T=read();
	while(T--)
	{
		n=read();
		if(n<=30)puts("NO");
		else
		{
			if(n==36)puts("YES
5 6 10 15");
			else if(n==40)puts("YES
6 10 15 9");
			else if(n==44)puts("YES
6 7 10 21");
			else printf("YES
%d %d %d %d
",6,10,14,n-30); 
		}
	} 
	return 0;
}

B. Captain Flint and a Long Voyage

题解

0~9里面肯定是8,9的二进制位最长,为了保证删后n位还是最大的,所以前3n位肯定全是9,后面的n位要全是8。注意要向上取整。

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
	return x*f;
}
int T;
int main()
{
	T=read();
	while(T--)
	{
		int n=read();
		int t=ceil((double)n/4.0);
		for(int i=1;i<=n-t;i++)putchar('9');
		for(int i=1;i<=t;i++)putchar('8');
		puts("");
	}
	return 0;
}

C. Uncle Bogdan and Country Happiness

题解

这题我都不知道我怎么过的,做的时候全程懵逼

就先考虑每个子树,设当前在子树的有(size)个人,开心的有(x)个人,不开心的有(size-x),有(2x=size+h[i]),所以必须保证(size+h)必须是偶数,而且这个(h)必须在([-size,size])区间里,否则不符合定义。然后开始考虑往儿子节点跑的过程,最坏情况下一路上可能大家全自闭了,所以这个东西没有下限,但是是有上限的,极限情况下在当前节点的人全自闭了,所以跑到儿子节点他们的(sum h_i)不可能超过(h_{now}+p_{now})。我就加了这么几个判断就A了,十分迷惑。

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
	return x*f;
}
const int maxn=100010;
int n,first[maxn],ce,a,b;
LL m,val[maxn],size[maxn],h[maxn];
struct Edge
{
	int u,v,next;
	Edge() {}
	Edge(int _1,int _2,int _3):u(_1),v(_2),next(_3) {} 
}e[maxn<<1];
void addEdge(int a,int b)
{
	e[++ce]=Edge(a,b,first[a]);first[a]=ce;
	e[++ce]=Edge(b,a,first[b]);first[b]=ce;
}
bool ok;
void dfs(int now,int fa)
{
	LL sum=0;
	size[now]=val[now];
	for(int i=first[now];i!=-1;i=e[i].next)
		if(e[i].v!=fa)dfs(e[i].v,now),size[now]+=size[e[i].v];
	if((size[now]+h[now])%2 || h[now]<-size[now] || h[now]>size[now]){ok=1;return;}
	for(int i=first[now];i!=-1;i=e[i].next)
		if(e[i].v!=fa)
			sum+=h[e[i].v];
	if(sum>h[now]+val[now]){
		ok=1;return;
	}
}
int main()
{
	int T=read();
	while(T--)
	{
		ce=-1;ok=0;
		n=read();m=read();
		for(int i=1;i<=n;i++)first[i]=-1,size[i]=0;
		for(int i=1;i<=n;i++)val[i]=read();
		for(int i=1;i<=n;i++)h[i]=read();
		for(int i=1;i<n;i++)a=read(),b=read(),addEdge(a,b);
		dfs(1,0);
		if(!ok)puts("YES");
		else puts("NO");
	}
	return 0;
}

D. Captain Flint and Treasure

题解

题目已经暗示的很明显了这个玩意是由若干棵有根树组成的,每一棵树的答案都是独立的,考虑依次处理树形DP,设(dp_i)表示i能取到的最大值,这个转移很简单,如果儿子的DP值是非负的,那么就可以累加上去。计算完答案后我们想如何还原答案,我一开始用的是双端队列在DP的时候插,感觉应该挺快的,结果pretest居然TLE了,于是就变成DP完了之后递归放数,对于一个(now),所有儿子(dp[v]<0)的都应放在(now)的后面,所有儿子(dp[v]>=0)的都应放在(now)的前面,做一个类似中序遍历的东西即可。

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
	return x*f;
}
const int maxn=200010;
int n,a[maxn],b[maxn],ce=-1,first[maxn],prt[maxn],len,size[maxn];
LL dp[maxn],ans;
struct Edge
{
	int u,v,next;
	Edge() {}
	Edge(int _1,int _2,int _3):u(_1),v(_2),next(_3) {} 
}e[maxn<<1];
void addEdge(int a,int b)
{
	if(a==-1)return;
	e[++ce]=Edge(a,b,first[a]);first[a]=ce;
}
void DP(int now)
{
	dp[now]=a[now];size[now]=1;
	for(int i=first[now];i!=-1;i=e[i].next)
	{
		DP(e[i].v);
		if(dp[e[i].v]>0)
			dp[now]+=dp[e[i].v],size[now]+=size[e[i].v];
	}	
}
void put(int now)
{
	for(int i=first[now];i!=-1;i=e[i].next)
		if(dp[e[i].v]>0)put(e[i].v);
	prt[++len]=now;
	for(int i=first[now];i!=-1;i=e[i].next)
		if(dp[e[i].v]<=0)put(e[i].v);
}
int main()
{
	mem(first,-1);
	n=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<=n;i++)b[i]=read(),addEdge(b[i],i); 
	for(int i=1;i<=n;i++)if(b[i]==-1)DP(i);
	for(int i=1;i<=n;i++)if(b[i]==-1)put(i);
	for(int i=1;i<=n;i++)ans+=dp[i];
	printf("%lld
%d",ans,prt[1]);
	for(int i=2;i<=n;i++)printf(" %d",prt[i]);
	return 0;
}

废话

原文地址:https://www.cnblogs.com/FYH-SSGSS/p/13408123.html