有N个袋子放成一排,每个袋子里有一定数量的糖果,lzs会随机选择连续的几个袋子,然后拿走这些袋子中包含最多糖果的袋子。现问你,在选择x个袋子的情况下,lzs最坏情况下,也就是最少会拿到多少个糖果?对于x取值为1到n都分别输出答案。(直接照搬题面啦..)
先预处理下,对每个位置i处理出一个区间[L,R]。表示这个范围中,a[i]是最大的,然后用线段树维护下最大值,循环1到n,对i,用a[i]的值去更新区间【1,R[i]-L[i]+1】的最小值。最后循环每次查询第i个位置的最小值是多少就行了......
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#define lson id<<1,l,m
#define rson id<<1|1,m+1,r
using namespace std;
typedef long long ll;
const int maxn=100000+1000;
const int inf=(1<<30);
struct segmenttree
{
int dt[maxn<<2];
void pushup(int id)
{
dt[id]=min(dt[id<<1],dt[id<<1|1]);
}
void build(int id,int l,int r)
{
if (l==r)
{
dt[id]=inf;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(id);
}
void modify(int L,int R,int id,int l,int r,int c)
{
if (L==l && R==r)
{
dt[id]=min(dt[id],c);
return;
}
int m=(l+r)>>1;
if (R<=m) modify(L,R,lson,c);
else if (L>m) modify(L,R,rson,c);
else modify(L,m,lson,c),modify(m+1,R,rson,c);
// pushup(id);
}
int query(int pos,int id,int l,int r)
{
if (l==r) return dt[id];
int res=dt[id];
int m=(l+r)>>1;
if (pos<=m) return min(res,query(pos,lson));
else return min(res,query(pos,rson));
}
}sgt;
int a[maxn],b[maxn];
int l[maxn],r[maxn];
int tt,n,m;
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d",&tt);
while(tt--)
{
scanf("%d",&n);
for (int i=1; i<=n; i++)
scanf("%d",&a[i]);
memset(l,0,sizeof l);
memset(r,0,sizeof r);
for (int i=1; i<=n; i++)
{
l[i]=i;
int j=i-1;
while (a[j]<=a[i] && j>=1)
{
l[i]=l[j];
j=l[j]-1;
}
}
for (int i=n; i>=1; i--)
{
r[i]=i;
int j=i+1;
while (a[j]<=a[i] && j<=n)
{
r[i]=r[j];
j=r[j]+1;
}
}
// for (int i=1; i<=n; i++)
// cout<<l[i]<<" "<<r[i]<<endl;
// cout<<endl;
sgt.build(1,1,n);
for (int i=1; i<=n; i++)
{
int len=(r[i]-l[i]+1);
sgt.modify(1,len,1,1,n,a[i]);
}
for (int i=1; i<=n; i++)
{
cout<<sgt.query(i,1,1,n)<<endl;
}
}
return 0;
}