51nod1431 快乐排队

18 篇文章 0 订阅
题目来源:  CodeForces
基准时间限制:1 秒 空间限制:131072 KB 分值: 80  难度:5级算法题
 收藏
 关注

有一群人在排队,如果某个人想排到前面去,可以花一元钱给直接站在他前面的人,然后和这个人交换位置。如果自己没有钱了,就不能和前面的人交换。

但是呢,队列里面的人觉得排他前面的所有人一定要比较有钱的,至少不能比他自己拿的少。否则里面就会有人生气。站在队头的人一定是高兴的。

现在给出一个队列的初始状态,问能不能调整队列,使得里面的人都高兴。


样例解释:样例1中,队尾的人可以和前面的人交换,变成9 10。


Input
单组测试数据。
第一行包含一个整数n (1 ≤ n ≤ 200,000),表示队列中的人数。
第二行包含n个空格分开的整数 ai (0 ≤ ai ≤ 10^9),ai表示队列中第i个人手上拿的钱。编号从队尾开始。
Output
对于每一组数据如果能够使得所有人高兴输出Happy,否则输出Sad。
Input示例
2
11 8
2
9 8
Output示例
Happy
Sad

题解:orz讨论区dalao。

对读入的所有数字加上其到队头的距离后的结果判重即可。

但是,为什么这样做是对的?考虑有可能造成序列不合法的数字对,必定是初始位置在前面的数值比后面的小。但是,要将这两个数移到一起,发现前者比后者小一,才能直接判断不合法。于是,需要把中间的数移开。假设中间的数字已经形成了合法的序列(如果不合法必定可以用同样的方法在中间的某个位置判断出来),如果中间的某个数字大于等于较大数,这个数字必定大于较小数,移走这个数字会给较小数加上一;如果中间的某个数字小于较大数,移走这个数字会给较大数减去一。由于中间的数字已经形成了合法的序列,满足单调不上升,因此大于等于较大数的数字都排在前面,必定可以从大到小依次通过较小数;对于较大数同理。不断地移走中间数的过程中,对于前后两者之差,任意一个中间数的影响恒为减一;因为要求两数并拢,所有中间数对两者差的综合影响恒为减去中间数的个数。于是就得到不合法状态的判断式子:存在i,j(i>j),满足a[i]-a[j]=i-j,其中a[k]表示队头起第k个数。将等式变换一下,即得:a[i]-i=a[j]-j。

注意本题中的读入是从队尾到队头的。


代码:

#include<bits/stdc++.h>
using namespace std;
int n,i,a[1000000];
int main(){
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]),a[i]+=i;
	sort(a+1,a+n+1);
	for(i=1;i<=n;i++)
	 if(a[i]==a[i-1]){
	 	printf("Sad");
	 	return 0;
	 }
	printf("Happy"); 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值