CodeForces 599C Day at the Beach(贪心)
题意:
给出一个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; }