fzu 11月赛E 2136 取糖果 线段树

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


你可能感兴趣的:(fzu 11月赛E 2136 取糖果 线段树)