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;
}
时间: 2024-12-27 06:29:20

Problem 2136 取糖果---FUOJ (线段树+维护)的相关文章

fzu 2136 取糖果(线段树)

题目链接:fzu 2136 2136 取糖果 题目大意:略. 解题思路:线段树区间合并.将袋子按照个数排序,每次将最小的放入线段树,如果当前连续的个数超过区间,那么说 明最小值即为最后加入的袋子糖果个数. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int maxn = 1e5 + 5; #defi

hdu 4037 Development Value(线段树维护数学公式)

Development Value Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 609    Accepted Submission(s): 118 Problem Description StarCraft 2 (SC2) is a famous game. More and more people fall in love wi

Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵

Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries on the string.There are two types of queries:1. Flipping the bits (i.e., changing all 1 to 0 and 0 to 1) between l and r (inclusive).2. Counting the

HDU 6155 Subsequence Count 线段树维护矩阵

Subsequence Count Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others) Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries on the string. There are two types of querie

【BZOJ4515】游戏,树链剖分+永久化标记线段树维护线段信息(李超线段树)

Time:2016.05.10 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 李超线段树 一开始听faebdc讲,并没有听的很懂ww 后来找到良心博文啊有木有 折越 首先可以把修改转换一下,因为那个dis非常不爽.显然s~t的路径有s~lca和lca~t组成.令d[x]表示x的深度,对于s~lca上面的点,修改的值相当于a*(d[s]-d[x])+b=-a*d[x]+(b-a*d[s]),lca~t上面的点的值相当于a*(d[s]+d[x]-2*d[lca])+b=a*d[x

[动态dp]线段树维护转移矩阵

背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区间,直接列出整个区间的dp方程.这个是基础,动态dp无论如何还是dp(这一步是一般是重点) 2.列出转移矩阵.由于有很多修改操作,我们将数据集中在一起处理,还可以利用矩阵结合律,并且区间比较好提取,(找一段矩阵就好了),修改也方便. 3.线段树维护矩阵.对于修改,我们就是在矩阵上进行修改,对于不同的

codeforces CF718C Sasha and Array 线段树维护矩阵

$ \Rightarrow $ 戳我进CF原题 C. Underground Lab time limit per test: 1 second memory limit per test: 256 megabytes input: standard input output: standard output The evil Bumbershoot corporation produces clones for gruesome experiments in a vast undergroun

CF877E Danil and a Part-time Job 线段树维护dfs序

\(\color{#0066ff}{题目描述}\) 有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0 共有 m 次操作,操作分为两种 get 询问一个点 x 的子树里有多少个 1 pow 将一个点 x 的子树中所有节点取反 对于每个 get 给出答案 \(\color{#0066ff}{输入格式}\) 第一行一个整数 n 第二行共 n?1 个整数,第 i 个数 \(x_i\) 表示 \(x_i\) 是 i+1 的父亲, 第三行给出每个点的初始权值 第四行一个整数 m 接下来

cf213E 线段树维护hash

链接 https://codeforces.com/contest/213/problem/E 题目大意 给出两个排列a.b,长度分别为n.m,你需要计算有多少个x,使 得\(a_1 + x; a_2 + x; a_3 + x... a_n + x\) 是b 的子序列(不连续的那种). 思路 巧妙啊 暴力直接扫会T 我们构造一个c数组,使得c[b[i]]=i 这样x+1到x+1+n就是一段连续的区间了233 插回去看看他们相对大小是不是和a数组相同 因为不连续所以线段树维护hash值,线段树按照