题目大意:
描述:
我们让 N 个人站成一排,编号为 1~N,每个人都有一个数字代表他这次比赛的成绩,对于每个人,如果他后面(编号大于他的人中)存在一个人的成绩大于等于他,那么他的嫉妒值为他们之间的距离。两个点 a和 b 之间的距离为 abs(a - b)。例如:{4,3,6,2},那么第 1 个人对第 3 个人有 2 点嫉妒值;第 2 个人对第 3 个人有 1 点嫉妒值,最大嫉妒值为 2。
输入:
第 1 行:1 个整数 N,代表这里有 N 个人(2 <= N <= 50000)。
接下来的 N 行:每行一个数 Ai(1 <= Ai <= 10^9), 表示第 i 个人的比赛成绩。
输出:
输出最大嫉妒值。
样例输入:
4
4
3
6
2
样例输出:
2
分析:
对于一个最厉害的人,他是没有嫉妒值的。也就是说,一个人越厉害,他所嫉妒的人越少,所以我要当最厉害的那个,即使不是也要向厉害的人靠拢,这样我才能有最小的嫉妒值。
进入正题,我把所有人的能力按照从大到小排序,然后一个人一个人的判断,如果这个人右边有比他能力大的,那么他所能产生的最大值嫉妒值一定是他和比他能力大的那些人中离他最远的人的距离。所以我按照能力值从大到小的顺序枚举的话,每次我只要记录最靠右的那个人就好了。对于每次枚举出来的这个人,如果他比之前记录的值更靠右,那么他没有嫉妒值,将最靠右的值更新为它。否则将他和最靠右的值只之间的距离和当前得到的最大嫉妒值相比较,已更新当前最大嫉妒值。
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct shu
{
int v;
int num;
}a[50050];
bool my_cmp(shu a,shu b)
{
if(a.v==b.v)return a.num>b.num;
return a.v>b.v;
}
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].v);
a[i].num=i;
}
sort(a+1,a+n+1,my_cmp);
int max=0;int w=a[1].num;
for(int i=1;i<=n;i++)
{
if(a[i].num>w)
{
w=a[i].num;
}
if(w-a[i].num>max)
{
max=w-a[i].num;
}
}
cout<<max<<endl;
}
后注:
做了几次校赛,感觉比赛真的不像是专题,并不是明确的算法,还是要尽量封装过程。先把问题分成若干我理论上能做到的事,然后再想合并和具体的代码实现。尽量不要很轻易的放弃一个超时的算法,而是要想想怎么通过数据结构或者处理技巧局部优化。
四月小结:
说真的,最后几篇有一点凑数的嫌疑,不过还是在这个月最后半个小时赶上了上个月的博客数。海风讲了一次课,不是我想象中的那么完美,不过学长说还好。下下周的树状数组一定要讲好。这个月开始的时候,一直在补之前落下的课程,后半个月开始刷题,树状数组刷了不少,不过感觉虽然是很有秀操作前途的数据结构,但是还是线段树功能更强大一点,五月优先学一下这个。五月应该会有一次校赛,三科期中考试,好好准备,好好发挥。准备比赛之前要自己仔细想一件事,算法大家都会,魔板都会去套,说不定代码能力还比你强,想超过别人,你要比别人强在哪里。算法原理的理解深度还是巧妙地思维转换。