CF 305 div2 D. Mike and Feet (递推)

来源:互联网 发布:网络低的回合制游戏 编辑:程序博客网 时间:2024/06/06 03:32

题目:http://codeforces.com/contest/548/problem/D

题意:给定n个数字a1,a2....an,定义一个大小为x的集合(x个相连的数字)的strength为集合里面最小的数的值。让你输出集合大小为(1~n)的集合的最大的strength。比如有10个数字,就要求出10个strength。大小为9的集合有2个(前9个数字和后9个数字),找出两个集合里面的最大的那个strength。

分析:对于每个数,假定这个数可以代表某个集合的strength,那么这个数在集合里面肯定最小,如果求出这个数能代表的集合的最大的大小Msize那么就好办了。求Msize可以分别求出左边和右边的范围。对于左边,如果a[i]>a[i+1]那么L[i]=1,如果a[i]<=a[i+1],那么a[i]的左端点可以接着a[i+1]的左端点向左推......,对于右边,跟左边同理。每个数的Msize求出来后,直接从最大的数字a[i]开始用就行了。

代码:

#include <iostream>#include <sstream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <vector>#include <string>#include <map>#include <set>//#include <unordered_map>//#include <unordered_set>#include <utility>#include <stack>#include <deque>#include <queue>#include <list>#include <bitset>using namespace std;typedef long long LL;typedef unsigned long long ULL;#define MAXN 1000005#define rep(i,x) for(int i=0;i<x;i++)int a[MAXN],L[MAXN],R[MAXN],s[MAXN],ans[MAXN];struct node{    int value;    int c;    bool operator < (const node &t) const    {        return value>t.value;    }}f[MAXN];int main(){    int n,i,j,k,c;    scanf("%d",&n);    for(i=0;i<n;i++)        scanf("%d",&a[i]);    for(i=n-1;i>=0;i--)    {        if(i+1<n && a[i]<=a[i+1])        {            j=i+1;            while(j<n && a[i]<=a[j])                j=j+L[j];            L[i]=j-i;            continue;        }        L[i]=1;    }    for(i=0;i<n;i++)    {        if(i-1>=0 && a[i]<=a[i-1])        {            j=i-1;            while(j>=0 && a[i]<=a[j])                j=j-R[j];            R[i]=i-j;            continue;        }        R[i]=1;    }    for(i=0;i<n;i++)    {        s[i]=L[i]+R[i]-1;        f[i].value=a[i];        f[i].c=s[i];    }    sort(f,f+n);    for(i=1,j=0;i<=n;i++)    {        while(f[j].c<i)            j++;        ans[i-1]=f[j].value;    }    for(i=0;i<n;i++)    {        printf("%d ",ans[i]);    }    return 0;}


0 0
原创粉丝点击