HLG 1524 最大 (离散化线段树)

链接: http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1524

Description

给包含n个数的初始序列,A[1], A[2], ..., A[n]。

给q多个操作,操作如下:

1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A[b] = v。

2 a b, 查询[a, b] 之间的相同数的连续和最大值。

在[a, b]区间内,相同数的连续和最大值就是Sum(A[i], A[i+1], A[j]), a <= i <= j <= b,并且A[i] = A[i+1] = A[i+2] = A[i+3] = ... = A[j]。

Input

有多组测试数据,不超过5组测试数据。

对于每组测试数据,第一个为 n (n<=10^5),第二行为n个数,每个数的范围[0, 1000]。

第三行为 q (q<=10^5),表示查询的次数。

接下来有q个操作,格式如下:

1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A[b] = v。

2 a b, 查询[a, b] 之间的相同数的连续和最大值。

其中 1 <= a <= b <=n,0 <= v <= 1000.

Output

每组测试数据先输出一行"Case id:",id从1开始计数。

对于每个查询,输出一行,包含一个整数,为相同数的连续和最大值。

Sample Input

5

2 2 1 2 3

3

2 1 4

1 1 3 2

2 1 5

7

120 985 727 979 68 558 732

4

1 2 5 627

2 2 7

2 4 5

1 5 7 571

Sample Output

Case 1:

4

8

Case 2:

2508

1254

代码如下: (这代码当时把我弄疯了)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define maxn 100005
#define clr(x)memset(x,0,sizeof(x))
using namespace std;

int max(int a,int b) { return a>b?a:b;}
int min(int a,int b) { return a<b?a:b;}
int lva[maxn<<4]; // 最左面的值
int lnu[maxn<<4]; // 最左面的数的个数
int rva[maxn<<4]; // 最右面的值
int rnu[maxn<<4]; // 最右面的数的个数
int mva[maxn<<4]; // 区间最大连续值
int add[maxn<<4]; // 延迟标记
int v[maxn], re[100005];

void creat(int l,int r,int rt)
{
    add[rt] = -1;
    if(l == r) {
        lva[rt] = rva[rt]=v[l];
        lnu[rt] = rnu[rt]=1;
        mva[rt] = v[l];
        return;
    }
    int m = (l+r) >> 1;
    creat(l, m, rt<<1);
    creat(m+1, r, rt<<1|1);
    lva[rt] = lva[rt<<1];
    lnu[rt] = lnu[rt<<1];
    rva[rt] = rva[rt<<1|1];
    rnu[rt] = rnu[rt<<1|1];
    if(lva[rt<<1] == lva[rt<<1|1] && lnu[rt<<1] == (m-l+1)) lnu[rt] += lnu[rt<<1|1];
    if(rva[rt<<1] == rva[rt<<1|1] && rnu[rt<<1|1] == r-m) rnu[rt] += rnu[rt<<1];
    mva[rt] = max(mva[rt<<1], mva[rt<<1|1]);
    if(rva[rt<<1] == lva[rt<<1|1]) {
        mva[rt] = max(mva[rt], rva[rt<<1]*rnu[rt<<1]+lva[rt<<1|1]*lnu[rt<<1|1]);
    }
}

void update(int L, int R, int c, int l, int r, int rt)
{
    if(L <= l && r <= R) {
        add[rt] = c;
        lva[rt] = rva[rt] = c;
        lnu[rt] = rnu[rt] = r-l+1;
        mva[rt] = c*(r-l+1);
        return;
    }
    int m = (l+r) >> 1;
    if(add[rt] != -1) {
        add[rt<<1] = add[rt<<1|1] = add[rt];
        lva[rt<<1] = rva[rt<<1] = lva[rt<<1|1] = rva[rt<<1|1] = add[rt];
        lnu[rt<<1] = rnu[rt<<1] = m-l+1;
        lnu[rt<<1|1] = rnu[rt<<1|1] = r - m;
        mva[rt<<1] = (m-l+1) * add[rt];
        mva[rt<<1|1] = (r-m) * add[rt];
        add[rt] = -1;
    }
    if(L <= m) update(L, R, c, l, m, rt<<1);
    if(R > m) update(L, R, c, m+1, r, rt<<1|1);
    lva[rt] = lva[rt<<1];
    lnu[rt] = lnu[rt<<1];
    rva[rt] = rva[rt<<1|1];
    rnu[rt] = rnu[rt<<1|1];
    if(lva[rt<<1] == lva[rt<<1|1] && lnu[rt<<1] == (m-l+1)) lnu[rt] += lnu[rt<<1|1];
    if(rva[rt<<1] == rva[rt<<1|1]&& rnu[rt<<1|1] == r-m) rnu[rt] += rnu[rt<<1];
    mva[rt]=max(mva[rt<<1],mva[rt<<1|1]);
    if(rva[rt<<1] == lva[rt<<1|1]) {
        mva[rt] = max(mva[rt], rva[rt<<1]*rnu[rt<<1]+lva[rt<<1|1]*lnu[rt<<1|1]);
    }
}

int query(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R) return mva[rt];
    int m = (l+r) >> 1;
    if(add[rt] != -1) {
        add[rt<<1] = add[rt<<1|1] = add[rt];
        lva[rt<<1] = rva[rt<<1] = lva[rt<<1|1] = rva[rt<<1|1] = add[rt];
        lnu[rt<<1] = rnu[rt<<1] = m-l+1;
        lnu[rt<<1|1] = rnu[rt<<1|1] = r - m;
        mva[rt<<1] = (m-l+1) * add[rt];
        mva[rt<<1|1] = (r-m) * add[rt];
        add[rt] = -1;
    }
    if(R <= m) return query(L, R, l, m, rt<<1);
    else if(L > m) return query(L, R, m+1, r, rt<<1|1);
    else {
        int res = 0;
        if(rva[rt<<1] == lva[rt<<1|1])
            res = (min(rnu[rt<<1], m-L+1) + min(lnu[rt<<1|1], R-m)) * rva[rt<<1];
        return max(res, max(query(L, m, l, m, rt<<1), query(m+1, R, m+1, r, rt<<1|1)));
    }
}

int n, a, b, c, m, op, cas = 1, top = 0, tot;

void Init()
{
    for(int i=1; i<=n; i++) scanf("%d",&v[i]);
    creat(1, n, 1);
    scanf("%d", &m);
    tot = 0;
}

int main()
{
    while(~scanf("%d", &n)) {
        Init();
        printf("Case %d:\n", cas++);
        while(m--) {
            scanf("%d", &op);
            if(op == 1) {
                scanf("%d %d %d", &a, &b, &c);
                update(a, b, c, 1, n, 1);
            }else {
                scanf("%d %d", &a, &b);
                printf("%d\n", query(a, b, 1, n, 1));
            }
        }
    }
    return 0;
}

HLG 1524 最大 (离散化线段树)

时间: 2024-10-09 19:45:50

HLG 1524 最大 (离散化线段树)的相关文章

poj 2528 Mayor&#39;s posters【离散化+线段树】

题目:poj 2528 Mayor's posters 题意:给一个长度非常长的墙上贴长度为ai的海报,由于有的会覆盖掉,求最后能看见的海报个数. 分析:题目和POJ2777 一模一样,方法也一样,只不过这个要离散化,其次要数组开大一点.至少2倍. 离散化的时候用了C++的 pair 类,还是比较好用的. 代码: #include <iostream> #include <algorithm> #include <utility> #include <cstrin

POJ 2299 离散化线段树

点击打开链接 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 40827   Accepted: 14752 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by

南阳理工 题目9:posters(离散化+线段树)

posters 时间限制:1000 ms  |  内存限制:65535 KB 难度:6 描述 The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally deci

Mayor&#39;s posters(离散化线段树)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 54067   Accepted: 15713 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

POJ 2528 Mayor&#39;s posters(离散化线段树)

Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for

bnu36905 Nested Segments 离散化+线段树

bnu36905 Nested Segments 离散化+线段树区间更新 也可以用离散化+set(或双向链表) #include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <queue> #include <string> #include <set> #include <stack> #include &l

POJ 2528 Mayor&amp;#39;s posters 离散化+线段树

题目大意:给出一些海报和贴在墙上的区间.问这些海报依照顺序贴完之后,最后能后看到多少种海报. 思路:区间的范围太大,然而最多仅仅会有10000张海报,所以要离散化. 之后用线段树随便搞搞就能过. 关键是离散化的方法,这个题我时隔半年才A掉,之前一直就TTT,我还以为是线段树写挂了. 当我觉得我自己的水平这样的水线段树已经基本写不挂的时候又写了这个题,竟然还是T. 后来我对照别人的代码,才发现是我的离散化写渣了. 以下附AC代码(79ms),这个离散化写的比較优雅.时间也非常快,以后就这么写了.

POJ 2528 Mayor&#39;s posters (离散化 + 线段树)

强烈不推荐在POJ做这道题!!! 强烈不推荐在POJ做这道题!!! 强烈不推荐在POJ做这道题!!! 推荐去UVA 10587 或 SCU 2249 POJ的数据比较水且可能有错,一些本来错误的数据但可以水过,以及在UVA与SCU同样题目都能AC的程序在POJ莫名WA了. 建议写完程序后跑下这组数据: 1 3 1 10 1 3 6 10 好多题解的答案是2,但答案明显是3,这是因为每个数字其实表示的是一个单位长度,并非一个点 , 这就会导致像这样的区间: 1-10 1-4 5-10 1-10 1

【POJ】2528 Mayor&#39;s posters ——离散化+线段树

Mayor's posters Time Limit: 1000MS    Memory Limit: 65536K Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city