NOIP提高组模拟赛夜间版2

没想到这个系列还能再更新

A. 装饰

这种题就需要大胆猜测打表验证

反正就是推出来了,式子变化一下就是题解式子,就是有亿点不简洁

我是这么想的(大概)

先排序,两个较小的颜色可以看成一个,这样只用考虑两种颜色,取法只有12

令两种颜色数量为a,b(a<b)

  1. a2<=b显然按照a1,b取2b有剩余,答案是a

  2. a2>b,那么每次操作可以令两种颜色数量差1,可以推一下,然后写出一个简单式子,实际上这样的结果是剩下的数量一定为00,10,01,11,02,20,实际上就是(a+b+c),那么答案其实就是(a+b+c)/3,当然也可以写一堆恶心式子

code
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long ll;

ll a[4];

ll work(){
	ll ans=0;
	a[2]+=a[1];
	if(a[3]<a[2]){a[2]^=a[3];a[3]^=a[2];a[2]^=a[3];}
	if(a[2]+a[2]<=a[3])return ans+a[2];
	ans+=a[3]-a[2];
	a[2]=a[3]=a[2]+a[2]-a[3];
	ans+=(a[2]/3)*2;
	a[2]%=3;a[3]%=3;
	if(a[2]==2)++ans;
	return ans;
}

int main(){
	freopen("decorate.in","r",stdin);
	freopen("decorate.out","w",stdout);
	int T;scanf("%d",&T);
	for(int ask=1;ask<=T;++ask){
		for(int i=1;i<=3;++i)scanf("%lld",&a[i]);
		sort(a+1,a+3+1);
		printf("%lld\n",work());
	}
	return 0;
}

B. 凉宫春日的消失

感谢数据,让我水了65pts

发现一定有解,跟dfs序有关,然后就莽了个按照dfs序排序

实际上离正解只有一步之遥

我们先让点集里的点按dfs序排序,然后相邻的两点都进行配对,第一个再和最后一个配对,这样我们把每个点配了两对

想一想深搜的路径,发现此时最多每条边经过两次

也就是说i=1cntpath<=2(n1)

我们只需要两两配对,那么只需要保留一半的路径,1,3,5....或者2,4,6....

他们有一个一定<=n1

简单判断一下一种方案是否可行即可

code
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=200005;

struct edge{int net,to;}e[maxn<<1|1];
int head[maxn],tot;
void add(int u,int v){
   e[++tot].net=head[u];
   head[u]=tot;
   e[tot].to=v;
}

int f[maxn][21],dfn[maxn],tim,dep[maxn],ls[maxn];

bool cmp(int x,int y){
	return dfn[x]<dfn[y];
}

void dfs(int x){
	dfn[x]=++tim;
	for(int i=head[x];i;i=e[i].net){
		int v=e[i].to;
		if(v==f[x][0])continue;
		f[v][0]=x;dep[v]=dep[x]+1;
		dfs(v);
	}
}

int LCA(int x,int y){
	if(dep[y]>dep[x]){x^=y;y^=x;x^=y;}
	for(int i=20;i>=0;--i)if(dep[x]-dep[y]>=(1<<i))x=f[x][i];
	if(x==y)return x;
	for(int i=20;i>=0;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}

bool check(int s,int n){
	if(s&1)return false;
	int sum=0;
	for(int i=1;i<=s;i+=2){
		int lca=LCA(ls[i],ls[i+1]);
		sum+=dep[ls[i]]-dep[lca]+dep[ls[i+1]]-dep[lca];
		if(sum>n)return false;
	}
	return true;
}
int main(){
	freopen("kieru.in","r",stdin);
	freopen("kieru.out","w",stdout);
	int n;scanf("%d",&n);
	for(int i=1;i<n;++i){
		int u,v;scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	dep[1]=1;dfs(1);
	for(int j=1;j<=20;++j)
	 for(int i=1;i<=n;++i)
	   f[i][j]=f[f[i][j-1]][j-1];
	int s;scanf("%d",&s);
	while(s){
		for(int i=1;i<=s;++i)scanf("%d",&ls[i]);
		sort(ls,ls+s+1,cmp);
		printf("Yes\n");
		if(check(s,n)){	
			for(int i=1;i<=s;i+=2)printf("%d %d\n",ls[i],ls[i+1]);
		}else {
			printf("%d %d\n",ls[1],ls[s]);
			for(int i=2;i<s;i+=2)printf("%d %d\n",ls[i],ls[i+1]);
		}
		scanf("%d",&s);
	}
	return 0;
}
posted @   Chen_jr  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示