有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; }