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

Codeforces #635 A~D

  • A.Ichihime and Triangle
  • B.Kana and Dragon Quest game
  • C.Linova and Kingdom
  • D.Xenia and Colorful Gems

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 
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 
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 
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 
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;
}

你可能感兴趣的:(codeforces题解)