Problem 2136 取糖果
Accept: 39 Submit: 101 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
1
5
1 3 2 4 5
Sample Output
1
3
3
4
5
题意:略。
思路:
看一下最暴力的。
min ( a1, a2, a3, a4 , a5 );
min ( a1a2 a2a3 a3a4 a4a5 );
min ( a1a2a3 a2a3a4 a3a4a5 );
min( a1a2a3a4 a2a3a4a5) ;
min( a1a2a3a4a5 );
在每一行中,取 最大值的最小值。
如果直接暴力会超时。
比赛的时候,没做出来,后来别人说他用 单调栈来做。
很多的题解有的用线段树,有的就直接剪枝过的。
首先 处理 每一个a[i] 为最大值时,能管辖的范围。也就是说,f[i].l f[i].r来保存管辖的位置。
管辖的范围,有什么用呢? 仔细想一想。
题意:每组数据输出n行,第i行表示lzs随机取连续的i个袋子时的最坏情况下能拿到的糖果数
其实,就是在1---管辖范围,当前这个数字,有没有机会成为 取连续 i 个袋子时的 最小值的机会。
线段树的怎么做呢?
其实就是处理后面的内容。
1.延迟更新每个数字的管辖范围。取最小值
2.取得每个位置的最小值。 //这两步,直接枚举就可以了。
1 #include<stdio.h> 2 3 4 struct node 5 { 6 int l; 7 int r; 8 }f[100003]; 9 int a[100003]; 10 int ans[100003]; 11 12 int main() 13 { 14 int T,n; 15 int i,j,k; 16 while(scanf("%d",&T)>0) 17 { 18 while(T--) 19 { 20 scanf("%d",&n); 21 for(i=1;i<=n;i++) 22 { 23 scanf("%d",&a[i]); 24 ans[i]=1000000000; 25 } 26 27 for(i=1;i<=n;i++) 28 { 29 for(j=i-1;j>=1;j--) 30 if(a[j]>a[i])break; 31 f[i].l=j+1; 32 33 for(j=i+1;j<=n;j++) 34 if(a[j]>a[i])break; 35 f[i].r=j-1; 36 } 37 38 for(i=1;i<=n;i++) 39 { 40 k=f[i].r-f[i].l+1; 41 for(j=1;j<=k;j++) 42 if(ans[j]>a[i]) 43 ans[j]=a[i]; 44 } 45 for(i=1;i<=n;i++) 46 printf("%d ",ans[i]); 47 } 48 } 49 return 0; 50 }