zoukankan      html  css  js  c++  java
  • 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;
    }
    

    废话

  • 相关阅读:
    Systemd 入门教程:实战篇
    Systemd 入门教程:命令篇
    awk详解
    yum Multilib version problems
    Oracle ORA 12541 报错解决过程
    创建表空间
    大文件按行分离脚本
    heartbeat安装与配置
    Keepalived安装配置
    速查表的名称和建表语句
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/13408123.html
Copyright © 2011-2022 走看看