• [HDU5306] Gorgeous Sequence


    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
    ",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();
        }
    }
    
    
  • 相关阅读:
    迭代器和生成器
    装饰器进阶
    闭包和装饰器
    函数的嵌套
    函数的参数
    什么是粘包现象
    模拟ssh远程命令执行
    客户端与服务端代码bug修复和加入循环
    用socket实现简单的套接字通讯
    网络编程之客户端和服务端,
  • 原文地址:https://www.cnblogs.com/mollnn/p/13217269.html
Copyright © 2020-2023  润新知