Problem 2136 取糖果
Accept: 92 Submit: 230
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
有N个袋子放成一排,每个袋子里有一定数量的糖果,lzs会随机选择连续的几个袋子,然后拿走这些袋子中包含最多糖果的袋子。现问你,在选择x个袋子的情况下,lzs最坏情况下,也就是最少会拿到多少个糖果?对于x取值为1到n都分别输出答案。
Input
第一行一个整数T,表示有T组数据。
每组数据先输入一行一个整数N(1<=N<=100000),表示袋子数,接下来一行输入N个正整数,输入的第i个数表示第i个袋子所装的糖果数。
Output
每组数据输出n行,第i行表示lzs随机取连续的i个袋子时的最坏情况下能拿到的糖果数。
Sample Input
151 3 2 4 5
Sample Output
13345
如果爆搜的话肯定会tle。所以要换一种思想来解决这个问题。
处理每一个a[i]能够管辖的范围,也就是a[i]在这个连续的范围内a[i]的值最大,那么假设a[3]管辖的范围为4,那么在连续的一个数,两个数,三个数,四个数中都是a[3]最大,所以最后枚举每一个数所管辖的范围即可。此题要求的inf很大,设小了会WA。
#include<stdio.h>
#define M 100007
#define inf 0x3f3f3f3f
int ans[M],a[M];
struct sa
{
int l,r;
}s[M];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
ans[i]=inf;
}
for(i=1;i<=n;i++)
{
for(j=i-1;j>=1;j--)
if(a[j]>a[i])break;
s[i].l=j+1;//求第i个数左边有几个数小于它
for(j=i+1;j<=n;j++)
if(a[j]>a[i])break;
s[i].r=j-1;//求第i个数右边有几个数小于它
}
for(i=1;i<=n;i++)
{
int len=s[i].r-s[i].l+1;//求第i个数一共有连续多少个数小于a[i]
for(j=1;j<=len;j++)//连续几个数的最大值都是a[i],所以枚举所有连续的可能性和a[i]比较
if(ans[j]>a[i])
ans[j]=a[i];
}
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}
return 0;
}