2018CCPC桂林站-Stone Game-排序贪心

题目描述:

Alice and Bob are always playing game! The game today is about taking out stone from the stone piles in turn.

There are n piles of stones, and the i-th pile contains A[i] stones.

As the number of stones in each pile differs from its neighbor’s, they determine to take out exactly one stone from one of them in one turn without breaking that property. Alice goes first.

The player who cannot take stone will lose the game.

Now you have to determine the winner given n numbers representing the piles, if they both play optimally.

You should notice that even a pile of 0 stone is still regarded as a pile!

输入描述:

The first line of input file contains an integer T (1≤T≤100), describing the number of test cases.

Then there are 2×T lines, with every two lines representing a test case.

The first line of each test case contains only one integer n (1≤n≤105) as described above.

The second line of that contains exactly n numbers, representing the number of stone(s) in a pile in order. All these numbers are ranging in [0,109].

It is guaranteed that the sum of n in all cases does not exceed 106.

输出描述:

You should output exactly T lines.

For each test case, print Case d: (d represents the order of the test case) first, then print the name of winner, Alice or Bob.

输入样例:

2
2
1 3
3
1 3 1

输出样例:

Case 1: Alice
Case 2: Bob

核心思想:

对于任意第i堆,

  1. 如果它比左右两堆都少,那么它一定可以被拿至0;
  2. 如果它比左右两堆都多,那么它一定保持大于左右两堆的状态,即左右两堆的个数的较大值+1是第i堆的下限
  3. 如果一多一少,那么少的那堆的个数+1是第i堆的下限

我们应该按个数从少到多处理每一堆,使每一堆的个数变成其下限。计拿走的石子个数为sum,sum为奇数则Alice胜,为偶数则Bob胜。

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+20;
struct node{
	int x,pos;
}h[N];//用于按个数排序 
int a[N];//用于访问相邻堆 
bool cmp(node p,node q)//用于排序 
{
	return p.x<q.x;
}
int main()
{
	int T,ca=0;
	cin>>T;
	while(++ca<=T)
	{
		int n,sum=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			h[i].pos=i;
			scanf("%d",&h[i].x);
			a[i]=h[i].x;
		}
		a[0]=a[n+1]=-1;
		sort(h+1,h+n+1,cmp);
		for(int i=1;i<=n;i++)
		{
			int t=h[i].pos;
			int mx=-1;
			if(a[t-1]<a[t])mx=max(mx,a[t-1]);
			if(a[t+1]<a[t])mx=max(mx,a[t+1]);
			a[t]=mx+1;
			sum+=h[i].x-a[t];
		}
		if(sum&1)printf("Case %d: Alice\n",ca);
		else printf("Case %d: Bob\n",ca);
	} 
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值