Problem 2136 取糖果---FUOJ (线段树+维护)

Posted 啦咯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Problem 2136 取糖果---FUOJ (线段树+维护)相关的知识,希望对你有一定的参考价值。

http://acm.fzu.edu.cn/problem.php?pid=2136

 题目大意: 给你n个袋子每个袋子里都装有糖果,然后呢你可以每次抽取一个连续的一个区间的袋子,然后带走里面最多糖果数目的袋子。

求区间长度从1到n你能带走的糖果数目最坏的情况是多少,也就是求所有区间的最大值的最小值

分析: 如果从小的开始查找他每次只要找到他能覆盖的区间,那么他就是这个区间的最大值,所以我们每次查询这个点就行了

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<ctype.h>
#include <iostream>
#include <map>
using namespace std;
#define INF 1e9+7
#define Lson r<<1|1
#define Rson r<<1
#define N 101000

int ans[N];
struct node
{
    int l,r,la,lb,Max;///la是这个区间左边连续的个数,lb是右边,Max是区间最大的连续序列
    int mid()
    {
        return (l+r)/2;
    }
    int len()
    {
        return (r-l+1);
    }
}a[N*10];
struct Node
{
    int x,y;
}P[N];

int cmp(Node c,Node d)
{
    return c.x<d.x;
}

void BuildTree(int r,int L,int R)
{
    a[r].l = L;
    a[r].r = R;
    a[r].la = a[r].lb = a[r].Max = 0;

    if(L == R)
        return;

    BuildTree(Lson, L, a[r].mid());
    BuildTree(Rson, a[r].mid()+1, R);
}
void Qurry(int r,int x,int y)
{
    if(a[r].l == a[r].r)
    {
        a[r].la = a[r].lb = a[r].Max = 1;
        return;
    }

    if(y > a[r].mid())
        Qurry(Rson, x, y);
    else
        Qurry(Lson, x, y);

    a[r].Max = max(a[Lson].Max, max(a[Rson].Max, a[Lson].lb+a[Rson].la));
    a[r].la = a[Lson].la;
    a[r].lb = a[Rson].lb;

    if(a[Lson].la == a[Lson].len())
        a[r].la += a[Rson].la;
    if(a[Rson].lb == a[Rson].len())
        a[r].lb += a[Lson].lb;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n;
        scanf("%d", &n);
        memset(P, 0, sizeof(P));
        for(int i=0; i<n; i++)
        {
            scanf("%d", &P[i].x);
            P[i].y = i;
        }

        BuildTree(1, 0, n-1);
        sort(P, P+n, cmp);

        int m=1;
        memset(ans, 0, sizeof(ans));
        for(int i=0; i<n; i++)
        {
            Qurry(1, P[i].x, P[i].y);///查询y点的最大序列
            int tmp=a[1].Max;

            while(m <= tmp)
                ans[m ++]=P[i].x;
        }

        for(int i=1; i<=n; i++)
            printf("%d\n", ans[i]);
    }
    return 0;
}

 

以上是关于Problem 2136 取糖果---FUOJ (线段树+维护)的主要内容,如果未能解决你的问题,请参考以下文章

2227 邮票--FUoj(链接表+树的直径)

BZOJ 1062 糖果雨

D1.Toy Train

Bzoj2330Scoi2011糖果

E - Problem E ( 吃糖) :HDU - 1205

WC2013 糖果公园