CodeForces 599C Day at the Beach(贪心)

传送门:http://codeforces.com/problemset/problem/599/C

题意:

给出一个n个房子的高度 数列,要求将房子连续分成几个块,使得每个块从小到大排序后,整个数列是非递减序列,问最多分成几个块?

 

思路:

用到贪心的思想,要想分最多的块,必须把尽可能小的区间分成一个块。

这里有两点:

1.当序列后面没有比自己小的数时,这个数就可以自成一块。

2.当序列后面有比自己小的数时,找到离自己最远的小于自己的数,这个区间组成一块,这样就不会违背题目排序规则。

 

代码思路就是要求到小于自己离自己最远的数的位置。用结构体排序,按数值大小由小到大排,若相同再按位置由小到大排。

这样只要从前往后扫,记录前面位置最大值就可以了。

 

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
struct node{
    int id,val;
}a[maxn];

bool cmp(node a, node b)//排序 
{
    if(a.val!=b.val)
        return a.val<b.val;
    return a.id<b.id;
}
int p[maxn];//记录后面比自己小离自己最远的位置
//如果后面没有比自己小的,记录为-1 
int main()
{
    int n,x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        a[i].id=i;
        a[i].val=x;
    }
    //按数值从小到大排,再按位置从小到大排 
    sort(a+1,a+n+1,cmp);
    int pre=0;//记录排序后,前面比自己小的数字最大的位置 
    for(int i=1;i<=n;i++)
    {
        if(a[i].id>pre)//后面没有比自己的数 
            p[a[i].id]=-1;
        else//有,记录 
            p[a[i].id]=pre;
        pre=max(pre,a[i].id);
    }
    int l=1;
    int ans=0;
    while(l<=n)//遍历 一遍 
    {
        if(p[l]==-1)//自成一块 
            l++;
        else
        {
            int temp=p[l];
            for(int i=l;i<=temp;i++)
                temp=max(temp,p[i]);
            l=temp+1;//与最远比自己小的 成一块 
        }
        ans++;
    }
    printf("%d\n",ans);
    return 0;
} 

 

猜你喜欢

转载自www.cnblogs.com/xiongtao/p/12162734.html