Educational Codeforces Round 85 [Rated for Div. 2]

Educational Codeforces Round 85 [Rated for Div. 2]

A. Level Statistics

给出n组(pi,ci),每轮可以选择给p和c同时+1,或者只给p 进行+1,两组数据之间可以进行多轮,判断给定序列是否合法。

Solution

判断不合法的情况:
1.pi < ci
2.pi < pi-1 || ci < ci-1
3.pi - pi-1 < ci - ci-1

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int SZ = 200 + 20;
int c[SZ],p[SZ];
bool flag;
int main()
{
	int T;
	scanf("%d",&T);
	while(T -- )
	{
		int n;
		scanf("%d",&n);
		flag = 0;
		for(int i = 1;i <= n;i ++)
		{
			scanf("%d%d",&p[i],&c[i]);
			if(p[i] < c[i]) 
			{
				flag = 1;
			}
		}
		if(flag == 1) 
		{
			printf("NO\n");
			continue;
		}
		for(int i = 2;i <= n;i ++ )
		{
			if(p[i] < p[i - 1] || c[i] < c[i - 1]) 
			{
				flag = 1;
				break;
			}
			if(p[i] - p[i - 1] < c[i] - c[i - 1]) 
			{
				flag = 1;
				break;
			}
		}
		if(flag  == 1) printf("NO\n");
		else printf("YES\n");
	}
	return 0;
} 

B. Middle Class

给出n个数字,和一个基准x。每次可选择n个数字中的任意个,然后把他们均匀分配,即把他们加起来再均分给这几个位置。为经过任意次操作后,大于等于基准x的数字的最大个数。

Solution

贪心的选大的,总比选小的优。
先排一下序,从最大的开始,然后依次加次大,第三大,看看当前和是否均分还能超过x,如果当前这个加上不能均分大于等于x。那么这个不加 ,并停止。选择的总个数就是答案。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int SZ = 1e5 + 20;
ll num[SZ];
int main()
{
	int T;
	scanf("%d",&T);
	while(T -- )
	{
		ll n,k;
		ll sum = 0;
		ll ans = 0;
		scanf("%lld%lld",&n,&k);
		for(int i = 1;i <= n;i ++ )
		{
			scanf("%lld",&num[i]);
		}
		sort(num + 1,num + n + 1);
		for(int i = n;i >= 1;i -- )
		{
			if((num[i] + sum) / (n - i + 1) >= k) 
			{
				sum += num[i];
				ans ++;
			}
			else break;			
		}
		printf("%lld\n",ans);
	}
	return 0;
} 

C. Circle of Monsters

给一个怪兽围成的圈,每次可以选择对一个怪兽造成1点伤害,每个怪兽有ai点生命值,如果它被击杀,那么他会爆炸对下一个怪兽造成bi点伤害,如果下一个怪兽被bi点伤害杀死,它也会爆炸下去,依次类推,如果它的下一个怪兽已经死了,那爆炸不会传递下去。问最少用多少枪可以让所有怪兽爆炸。

Solution

让爆炸伤害最大化,则用枪的次数最少。最大化爆炸伤害,就是一次爆炸就可以引发全部的爆炸。
处理方法就是先把每个怪兽的血量打到小于等于上一个怪兽的bi。这样就能保证炸一个全炸,然后在选择一个当前血量最低的打爆。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int SZ = 3e5 + 10;
struct zt
{
	ll a,b;
}node[SZ];
int main()
{
	int T;
	scanf("%d",&T);
	while(T -- )
	{
		int n;
		ll ans = 0;
		ll minn;
		scanf("%d",&n);
		for(int i = 1;i <= n;i ++ )
			scanf("%lld%lld",&node[i].a,&node[i].b);
		if(node[1].a > node[n].b)
		{
			 ans += (node[1].a - node[n].b);
			 node[1].a = node[n].b;
		}	
		minn = node[1].a;
		for(int i = 2;i <= n;i ++ )
		{
			if(node[i].a > node[i - 1].b) 
			{
				ans += node[i].a - node[i - 1].b;
				node[i].a = node[i - 1].b;
			}
			minn = min(minn,node[i].a);
		}
		printf("%lld\n",ans+ minn);
	}
	return 0;
} 

D. Minimum Euler Cycle

给一个完全图,把每条边走一遍,a-b ,b-a算两条边,点可以走无限次,输出字典序最小的欧拉回路的l到r段。

Solution

可以看出
1213141516…1n
2324252627…2n
3435363738…3n

1
这样可以保证字典序最小

并且每一组的个数是2*(n - 1)个共n - 1组, 最后还有一个单独的1。

我们只要找到l和r所在的分组,然后找规律输出即可。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
ll n,l,r;
int main()
{
	int T;
	scanf("%d",&T);
	while(T -- )
	{
		scanf("%lld%lld%lld",&n,&l,&r);
		ll i,j; //i为l的分组   j为r的分组 
		for(i = 1;i <= n - 1;i ++ )
		{
			if(l > 2 * (n - i)) l -= 2 * (n - i); 
			else break;
		}
		for(j = 1;j <= n - 1;j ++ )
		{
			if(r > 2 * (n - j)) r -= 2 * (n - j);
			else break;
		} 
		//如果在同一组 只输出本区间的l到r  特殊处理最后一个单独的1 
		if(i == j)
		{
			if(j == n) printf("1");
			else 
			for(ll p = l;p <= r;p ++ )
			{
				if(p % 2 == 1)	printf("%lld ",i);	
				else printf("%lld ",i + p/2);
			}	
		}
		else //l和r在不同分组,单独处理l所在分组 r所在分组 和中间的组 
		{
			for(ll p = l;p <= 2 * (n - i);p ++ )
			{
				if(p % 2 == 1)	printf("%lld ",i);	
				else printf("%lld ",i + p/2);
			}
			for(ll p = i + 1;p <= j - 1;p ++ )
			{
				for(ll q = 1;q <= 2 * (n - p);q ++ )
				if(q % 2 == 1)	printf("%lld ",p);	
				else printf("%lld ",p + q/2);
			}
			if(j == n) printf("1");//单独处理最后一个1 
			else 
			for(ll p = 1;p <= r;p ++ )
			{
				if(p % 2 == 1)	printf("%lld ",j);	
				else printf("%lld ",j + p/2);
			}
		}
		printf("\n");
	}
	return 0;
} 

2020.4.13

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值