Educational Codeforces Round 79 (Rated for Div. 2)——B. Verse For Santa、C. Stack of Presents简要题解

题目传送门:https://codeforces.com/contest/1279/problem/B
题目传送门:https://codeforces.com/contest/1279/problem/C

题目大意:

B. Verse For Santa: 你要给圣诞老人唱n段诗,每段都有其时长,但是圣诞老人只有耐心听s分钟,而且唱诗是有顺序的,你只能跳过其中一段。问你最多能给圣诞老人唱几段诗?
C. Stack of Presents: 给出一个栈中的礼物,编号为1~n,顶部编号为a1,接下来为a2,底部为an,每个编号唯一。给出一个发送礼物的清单,编号为b1,b2,…bn,圣诞老人必须按编号顺序发送礼物,每次发送礼物,从栈中寻找礼物,要想拿走这个礼物,必须先拿走这个礼物前面的礼物,假如这个礼物前面有k个礼物,那么所花费时间为2k + 1秒,并且排好序后重新放回栈中,,问我们发送清单的礼物所需要花费的最短时间?

思路分析及AC代码:

B题: 其实是一个贪心的思想,所跳过的那一段一定是满足条件的情况下最长的一段。所以我们要做的是一直给圣诞老人唱,然后记录一下所唱过的诗中最长的一段。当所唱的诗的段落的总长度减去最长的一段后仍然超过规定时间的时候,就停止。因为此时无论怎么跳都无法满足题意。

#include
#include
#include
#include
#include
#define PI 3.1415926
typedef long long ll;
using namespace std;
int main()
{
	int t=0;
	cin>>t;
	while(t--)
	{
		ll n=0,k=-1,ans=0,ansid=0;
		ll s=0,b=0;
		ll a[100010]={0};
		scanf("%lld",&n);
		scanf("%lld",&s);
		ll x=0;
		for(ll i=1;i<=n;i++)
		scanf("%lld",&a[i]);
		for(ll i=1;i<=n;i++)
		{
			b+=a[i];
		}
		if(b<=s)
		{
			cout<<0<<endl;
			continue;
		}
		else
		{
				for(ll i=1;i<=n;i++)
			{
				x+=a[i];
				if(k<a[i])//k是最长的段落的时长
            {
                ans = i;
                k = a[i];
            }
            if(x - k <= s)//满足条件时,也就是已唱的减去最长时长小于规定时间
            {
                ansid = ans;
            }
			} 
			cout<<ansid<<endl;
		}
	}
	return 0;
}

C题: 首先用一个pos数组记录a数组中每个数字的位置,然后动态更新一下礼物最深处的深度就行了。找到最大深度后,用这个深度减去已经送出的礼物的个数再乘以2就是把这些礼物拿出来,再排好序后放回去的时间,然后再加上送出去n个礼物的时间就是总时间。

#include
#include
#include
#include
#include
#define PI 3.1415926
typedef long long ll;
using namespace std;
int main()
{
	ll t=0;
	cin>>t;
	static ll a[100010]={0};
	static ll pos[100010]={0};
	while(t--)
	{
		ll m=0,n=0,b=0,ans=0,bottom=-1;
		scanf("%lld%lld",&m,&n);
		for(ll i=1;i<=m;i++)
		{
			scanf("%lld",&a[i]);
			pos[a[i]]=i;//记录a数组中每个数字的位置 
		}
		for(ll i=1;i<=n;i++)
		{
			cin>>b;
			if(pos[b]>bottom)//如果当前礼物的位置在当前最深位置的下面 
			{
				bottom=pos[b];//更新最深位置 
				ans+=(bottom-i)*2;//此时已经有i个礼物被送出去了,所以要用当前最深位置减去i
				//意思就是把这些礼物都拿出来,再排好序放回去 
			}
		}
		ans+=n;//ans原本是掏礼物和排好序后放入栈中的时间,再加上送出去n个礼物的时间 
		cout<<ans<<endl;
	}
	return 0;
}

注意事项:

B题注意一下一种特殊情况,就是当跳过一个最大段的时候,后面可能能再给圣诞老人唱好多个很短的段,所以统计段落的时候要考虑到这种情况。(这也是为什么之前的写法一直过不了的原因)。
C题注意题意的理解,圣诞老人送礼物是一个一个送的,而不是将该送的礼物一口气排好序之后再送。注意题意的理解!!!

你可能感兴趣的:(ACM)