Codeforces Round #635 (Div. 2)(A~D)题解

A.Ichihime and Triangle

题意:
给你四个正整数 a , b , c , d a,b,c,d a,b,c,d,表示三个区间 [ a , b ] , [ b , c ] , [ c , d ] [a,b],[b,c],[c,d] [a,b],[b,c],[c,d]
在每个区间取出一个数,使得这三个数能构成三角形的三条边.
题解:
直接取b,c,c即可,这样就保证了任意两边大于第三边.

#include<bits/stdc++.h> 
using namespace std;
int t,a,b,c,d;
void solve(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%d%d",&a,&b,&c,&d);
		printf("%d %d %d\n",b,c,c); 
	}
}
int main(void){
	solve();
	return 0;
}

B.Kana and Dragon Quest game

题意:
给你三个正整数 x , n , m x,n,m x,n,m.表示初始有 x x x个生命值, n n n次操作 1 1 1, m m m次操作 2 2 2.
操作 1 : x = ( x / 2 ) + 10 1:x=(x/2)+10 1:x=(x/2)+10.
操作 2 : x = x − 10 2:x=x-10 2:x=x10.
问最后能不能使得 x < = 0 x<=0 x<=0.
题解:
贪心即可,先进行1操作,再进行2操作,注意一下,1操作会有让x值增大的情况,判断一下.

#include<bits/stdc++.h> 
using namespace std;
int t,x,n,m;
void solve(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%d",&x,&n,&m);
		while(n--){
			if((x/2)+10>x) break;
			x=(x/2)+10;
		}
		if(m*10<x) printf("NO\n");
		else printf("YES\n");
	}
}
int main(void){
	solve();
	return 0;
}

C.Linova and Kingdom

题意:
给你一棵树,1号节点为首都,让你选出k个城市为工业城市,每一个工业城市的贡献值为该城市到首都的简单路径上非工业城市的数量,求选出k个城市后贡献值的最大值是多少
题解:
首先,要使得一个城市为工业城市,那么必须这个城市的所有子城市都必须要为工业城市,否则不是最优.假如有子城市不为工业城市,那么选择那个子城市的贡献就会比当前城市的贡献多deep[当前城市]-deep[子城市] (deep为深度).
给出两个数组, c o s t , t t cost,tt cost,tt.
c o s t [ i ] cost[i] cost[i]代表选择当前节点为工业城市后的总贡献值(包括所有子节点).显然
c o s t [ i ] = s i z [ i ] ∗ ( d e e p [ i ] − 1 ) cost[i]=siz[i]*(deep[i]-1) cost[i]=siz[i](deep[i]1).
t t [ i ] tt[i] tt[i]代表选择当前节点为工业城市后的净利润,即
t t [ i ] = c o s t [ i ] − tt[i]=cost[i]- tt[i]=cost[i] ∑ \sum c o s t [ s o n [ i ] ] cost[son[i]] cost[son[i]].
然后将tt数组排序,取前m个即可.

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int MAX = 2e5+5;
int n,m,deep[MAX],u[MAX*2],v[MAX*2],cnt,first[MAX],nextt[MAX*2];
int siz[MAX];
ll cost[MAX],tt[MAX],ans;
vector<int> list1;
void add(int a,int b){
	u[cnt]=a,v[cnt]=b;
	nextt[cnt]=first[u[cnt]];
	first[u[cnt]]=cnt;++cnt;
}
void dfs(int dot,int pre){
	siz[dot]=1;
	deep[dot]=deep[pre]+1;
	for(int num = first[dot];num!=-1;num=nextt[num]){
		if(v[num]==pre) continue;
		dfs(v[num],dot);
		siz[dot]+=siz[v[num]];
	}
	cost[dot]=1ll*siz[dot]*(deep[dot]-1);
	tt[dot]=cost[dot];
	for(int num=first[dot];num!=-1;num=nextt[num]){
		if(v[num]==pre) continue;
		tt[dot]-=cost[v[num]];
	}
}
bool cmp(int a,int b){
	return a>b;
}
void solve(){
	scanf("%d%d",&n,&m);
	memset(first,-1,sizeof(first));
	for(int i=1;i<n;++i){
		int a,b;
		scanf("%d%d",&a,&b);
		add(a,b);add(b,a);
	}
	dfs(1,0);
	for(int i=1;i<=n;++i){
		list1.push_back(tt[i]);
	}
	sort(list1.begin(),list1.end(),cmp);
	for(int i=1;i<=m;++i) ans+=list1[i-1];
	printf("%lld\n",ans);
}
int main(void){
	solve();
	return 0;
}

D.Xenia and Colorful Gems

题意:
给你三个数组,长度分别为 n r , n g , n b . nr,ng,nb. nr,ng,nb.
让你分别从三个数组中挑出一个数, x , y , z x,y,z x,y,z
使得 ( x − y ) ∗ ( x − y ) + ( y − z ) ∗ ( y − z ) + ( x − z ) ∗ ( x − z ) (x-y)*(x-y)+(y-z)*(y-z)+(x-z)*(x-z) (xy)(xy)+(yz)(yz)+(xz)(xz)最小.
题解:
枚举 a a a数组中的每一个数,然后在 b b b, c c c数组中找出最接近a的数, b 1 , b 2 , c 1 , c 2 b1,b2,c1,c2 b1,b2,c1,c2.
b 1 < = a , b 2 > = a , c 1 < = a , c 2 > = a . b1<=a , b2>=a , c1<=a , c2>=a. b1<=a,b2>=a,c1<=a,c2>=a.
然后分类讨论一下取最小值即可,b,c数组也进行一遍如上操作.

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int MAX = 2e5+5;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int t,nr,ng,nb,a[MAX],b[MAX],c[MAX];
ll ans=INF;
ll cal(ll x,ll y,ll z){
	return (x-y)*(x-y)+(y-z)*(y-z)+(x-z)*(x-z);
}
void solve(){
	scanf("%d",&t);
	while(t--){
		ans=INF;
		scanf("%d%d%d",&nr,&ng,&nb);
		for(int i=0;i<nr;++i) scanf("%d",&a[i]);
		for(int i=0;i<ng;++i) scanf("%d",&b[i]);
		for(int i=0;i<nb;++i) scanf("%d",&c[i]);
		sort(a,a+nr);sort(b,b+ng);sort(c,c+nb);
		for(int i=0;i<nr;++i){
			int y = lower_bound(b,b+ng,a[i])-b;
			int z = lower_bound(c,c+nb,a[i])-c;
			if(y==ng) --y;if(z==nb) --z;
			ans=min(ans,cal(a[i],b[y],c[z]));
			if(y>0) ans=min(ans,cal(a[i],b[y-1],c[z]));
			if(z>0) ans=min(ans,cal(a[i],b[y],c[z-1]));
			if(y>0&&z>0) ans=min(ans,cal(a[i],b[y-1],c[z-1]));
		}
		for(int i=0;i<ng;++i){
			int x = lower_bound(a,a+nr,b[i])-a;
			int z = lower_bound(c,c+nb,b[i])-c;
			if(x==nr) --x;if(z==nb) --z;
			ans=min(ans,cal(a[x],b[i],c[z]));
			if(x>0) ans=min(ans,cal(a[x-1],b[i],c[z]));
			if(z>0) ans=min(ans,cal(a[x],b[i],c[z-1]));
			if(x>0&&z>0) ans=min(ans,cal(a[x-1],b[i],c[z-1]));
		}
		for(int i=0;i<nb;++i){
			int x = lower_bound(a,a+nr,c[i])-a;
			int y = lower_bound(b,b+ng,c[i])-b;
			if(x==nr) --x;if(y==ng) --y;
			ans=min(ans,cal(a[x],b[y],c[i]));
			if(x>0) ans=min(ans,cal(a[x-1],b[y],c[i]));
			if(y>0) ans=min(ans,cal(a[x],b[y-1],c[i]));
			if(x>0&y>0) ans=min(ans,cal(a[x-1],b[y-1],c[i]));
		}
		printf("%lld\n",ans);
	}
}
int main(void){
	solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值