题目: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;
}