码迷,mamicode.com
首页 > 其他好文 > 详细

[HDU5306] Gorgeous Sequence - 线段树区间最值操作

时间:2020-07-01 09:26:51      阅读:39      评论:0      收藏:0      [点我收藏+]

标签:i++   最大值   线段   个数   har   getchar   ++   const   str   

Description

维护数列,支持区间 min 操作,询问区间 max,询问区间和。

Solution

区间最值操作入门题

对线段树每个结点维护最大值 \(maxnum\),最大值个数 \(maxcnt\),次大值 \(secnum\),区间和 \(sum\)

修改某个节点时,设操作数为 \(x\),若 \(maxnum \le x\) 则退出,若 \(secnum \ge x\) 则继续递归,若 \(secnum < x < maxnum\) 则修改当前结点值(\(sum\) 减少 \((maxnum-a)maxcnt\)\(maxnum\) 变为 \(a\)),同时送给该点一个 lazy tag

下传 lazy tag 时,很显然一定不会出现需要递归修改的情况,于是也可以借用修改操作来处理

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 4000005;

#define lc p*2,l,(l+r)/2
#define rc p*2+1,(l+r)/2+1,r

int min(int x,signed y)
{
    return min(x,1ll*y);
}

int min(signed x,int y)
{
    return min(1ll*x,y);
}

int max(int x,signed y)
{
    return max(x,1ll*y);
}

int max(signed x,int y)
{
    return max(1ll*x,y);
}

struct Node
{
    signed maxnum,maxcnt,secnum,tag,istag;
    int sum;
    Node()
    {
        tag = 4e9;
    }
    Node(int t1,int t2,int t3,int t4,int t5,int t6)
    {
        maxnum = t1;
        maxcnt = t2;
        secnum = t3;
        sum = t4;
        tag = t5;
        istag = t6;
    }
    void set(int x)
    {
        maxnum = x;
        maxcnt = 1;
        secnum = -1;
        sum = x;
        tag = 4e9;
        istag = 0;
    }
    Node operator + (const Node &b) const
    {
        Node res;
        res.maxnum = max(maxnum, b.maxnum);
        res.maxcnt = (maxnum==res.maxnum)*maxcnt + (b.maxnum==res.maxnum)*b.maxcnt;
        // 次小值计算一开始写错了
        if(res.maxnum == maxnum) res.secnum = secnum;
        else res.secnum = maxnum;
        if(res.maxnum == b.maxnum) res.secnum = max(res.secnum, b.secnum);
        else res.secnum = max(res.secnum, b.maxnum);
        res.sum = sum + b.sum;
        res.tag = 4e9;
        res.istag = 0;
        return res;
    }
} node[N];

Node NULLNODE = {-1,0,-1,0,4e9,0};

int n,m,a[N],t1,t2,t3,t4;

void build(int p,int l,int r)
{
    if(l==r)
    {
        node[p].set(a[l]);
    }
    else
    {
        build(lc);
        build(rc);
        node[p]=node[p*2]+node[p*2+1];
    }
}

void beat(int p,int l,int r,int x)
{
    if(node[p].maxnum > x)
    {
        node[p].sum -= (node[p].maxnum - x)*node[p].maxcnt;
        node[p].maxnum = x;
    }
    node[p].tag = min(node[p].tag, x);
    node[p].istag = 1;
}

void pushdown(int p,int l,int r)
{
    if(node[p].istag)
    {
        int t=node[p].tag;
        beat(lc,t);
        beat(rc,t);
        node[p].tag = 4e9;
        node[p].istag = 0;
    }
}

void modify(int p,int l,int r,int ql,int qr,int x)
{
    if(l>qr || r<ql) return;
    if(l>=ql && r<=qr)
    {
        if(node[p].secnum >= x)
        {
            pushdown(p,l,r);
            modify(lc,ql,qr,x);
            modify(rc,ql,qr,x);
            node[p] = node[p*2]+node[p*2+1];
        }
        else
        {
            beat(p,l,r,x);
        }
    }
    else
    {
        pushdown(p,l,r);
        modify(lc,ql,qr,x);
        modify(rc,ql,qr,x);
        node[p] = node[p*2]+node[p*2+1];
    }
}

Node query(int p,int l,int r,int ql,int qr)
{
    if(l>qr || r<ql) return NULLNODE;
    if(l>=ql && r<=qr) return node[p];
    pushdown(p,l,r);
    return query(lc,ql,qr) + query(rc,ql,qr);
}

int read()
{
    int x=0,f=1;
    char ch=getchar();
    for(; ch<‘0‘||ch>‘9‘; ch=getchar())if(ch==‘-‘)f=-1;
    for(; ch>=‘0‘&&ch<=‘9‘; ch=getchar())x=x*10+ch-‘0‘;
    return x*f;
}

void read(int &x)
{
    x=read();
}

void write(int x)
{
    printf("%lld\n",x);
}

void solve()
{
    ios::sync_with_stdio(false);
    read(n);
    read(m);
    for(int i=1; i<=n; i++) read(a[i]);
    build(1,1,n);
    for(int i=1; i<=m; i++)
    {
        read(t1);
        read(t2);
        read(t3);
        if(t1==0)
        {
            read(t4);
            modify(1,1,n,t2,t3,t4);
        }
        if(t1==1)
        {
            write(query(1,1,n,t2,t3).maxnum);
        }
        if(t1==2)
        {
            write(query(1,1,n,t2,t3).sum);
        }
    }
}

signed main()
{
    int t;
    read(t);
    while(t--)
    {
        solve();
    }
}

[HDU5306] Gorgeous Sequence - 线段树区间最值操作

标签:i++   最大值   线段   个数   har   getchar   ++   const   str   

原文地址:https://www.cnblogs.com/mollnn/p/13217269.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!