Looksery Cup 2015 G. Happy Line

1.题目描述:点击打开链接

2.解题思路:本题利用贪心法解决。不过贪心的思想却是非常巧妙的。想象有一个阶梯,第n个人的阶梯高度是1,然后第n-1个人的阶梯高度是2,第1个人的阶梯高度是n。程序中用base[i]表示第i位的阶梯高度。注意:题目中,“前面”只的是序号大的,“后面”指的是序号小的。那么,如果一个人沿着阶梯下降,说明他在往前移动;反之则是在往后移动。由于不管怎么交换,最终想要达到的状态只有一个,即前面的人的钱尽量多,后面的人的钱尽量少,那么我们就可以事先用b[i]表示扣除阶梯的高度后还剩下的钱数,对数组b从小到大排序,即表示让前面的人的钱尽可能多,后面的人的钱尽可能的少。排序之后把阶梯加回去,就是最终的钱数,只需要检查此时钱数是否呈现非递减趋势即可。(理解这个做法费了很长时间,智商捉急了==)

3.代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;


#define me(s) memset(s,0,sizeof(s))
#define For(i,n) for(int i=0;i<(n);i++)
#define pb push_back
#define sz size
#define clr clear
#define F(a,b) for(int i=a;b;i++)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

const int maxn=200200;

int n,a[maxn],base[maxn],b[maxn];

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);

	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%d",a+i);
		base[i]=n-1-i;
		b[i]=a[i]-base[i];
	}
	sort(b,b+n);
	bool flag=true;
	for(int i=0;i<n;i++)
	{
		a[i]=base[i]+b[i];
		if(i&&a[i]<a[i-1])
		{
			flag=false; break;
		}
	}
	if(flag==false)
	{
		puts(":(");
	}
	else
	{
		for(int i=0;i<n;i++)
			printf("%d%c",a[i],(i==n-1)?10:32);
	}

    return 0;
}

你可能感兴趣的:(Looksery Cup 2015 G. Happy Line)