HDU 5306 Gorgeous Sequence (吉老师线段树入门)

第一次接触吉老师的线段树,写点东西以后复习用
区间有min操作所以我们对树的操作有点不一样
树的结点保存这几个信息

  • 总和 s
  • 区间最大值 mx
  • 区间次大值 se
  • 区间最大值的个数 t
  • lazy tag
    取min更新 其实有点维护最大值的意思
    当修改值 val >= mx 直接 return 不用更新
    val <= se 的时候 再暴力递归给子结点处理
    当 se < val < mx 时候可以打上标记 总值 s -= 最大值变成val的差值(即mx -val) 乘上最大值个数
#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define pb(x)   push_back(x)
#define il inline
#define re register
#define IO; ios::sync_with_stdio(0);cin.tie(0);
#define ls (o<<1)
#define rs (o<<1|1)
#define pii pair<int,int>
using namespace std;
const int maxn = 1000010;
const int maxm = 400010;
const int INF = 0x3f3f3f3f;
const ll LINF = 3e17+1;
const int mod = 1e9+7;
int n, r, c, m;
inline int read(){
    
    
    register int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){
    
    if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){
    
    x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return (f==1)?x:-x;
}
struct node {
    
    int t,ma,se,tag;ll s;}tr[maxn<<2];
int a[maxn];
void pushup(int o)
{
    
    
    if (tr[ls].ma == tr[rs].ma)
    {
    
    
        tr[o].ma = tr[ls].ma;
        tr[o].t = tr[ls].t + tr[rs].t;
        tr[o].se = max(tr[ls].se,tr[rs].se);
    }
    else if (tr[ls].ma > tr[rs].ma)
    {
    
    
        tr[o].ma = tr[ls].ma, tr[o].t = tr[ls].t;
        tr[o].se = max(tr[ls].se,tr[rs].ma);
    }
    else
    {
    
    
        tr[o].ma = tr[rs].ma, tr[o].t = tr[rs].t;
        tr[o].se = max(tr[rs].se,tr[ls].ma);
    }
    tr[o].s = tr[ls].s + tr[rs].s;
}
void pushdown(int o)
{
    
    
    int val = tr[o].ma;
    if (tr[ls].se < val && val < tr[ls].ma )
    {
    
    
        tr[ls].s -= 1ll*tr[ls].t*(tr[ls].ma - val);
        tr[ls].ma = val;tr[ls].tag = 1;
    }
    if (tr[rs].se < val && val < tr[rs].ma )
    {
    
    
        tr[rs].s -= 1ll*tr[rs].t*(tr[rs].ma - val);
        tr[rs].ma = val;tr[rs].tag = 1;
    }
    tr[o].tag = 0;
}
void build(int o, int l, int r)
{
    
    
    tr[o].se = -1; tr[o].tag = 0;
    if (l == r)
    {
    
    
        tr[o].s = tr[o].ma = a[l];
        tr[o].t = 1;
        return ;
    }
    int mid = (l+r)>>1;
    build(ls,l,mid);build(rs,mid+1,r);
    pushup(o);
}
void modify(int o, int l, int r, int ql, int qr, int val)
{
    
    
    if (ql <= l && r <= qr)
    {
    
    
        if (val >= tr[o].ma)    return ;
        if (tr[o].se < val)
        {
    
    
            tr[o].s -= 1ll*tr[o].t*(tr[o].ma-val);
            tr[o].ma = val;tr[o].tag = 1;
            return ;
        }
    }
    int mid = (l+r)>>1;
    if (tr[o].tag)  pushdown(o);
    if (ql <= mid)  modify(ls,l,mid,ql,qr,val);
    if (mid < qr)   modify(rs,mid+1,r,ql,qr,val);
    pushup(o);
}
int querymx(int o, int l, int r, int ql, int qr)
{
    
    
    if (ql <= l && r <= qr)
    {
    
    
        return tr[o].ma;
    }
    int mid = (l+r)>>1;
    if (tr[o].tag)  pushdown(o);
    int res = -INF;
    if (ql <= mid)  res = max(res,querymx(ls,l,mid,ql,qr));
    if (mid < qr)   res = max(res,querymx(rs,mid+1,r,ql,qr));
    return res;
}
ll querysum(int o, int l, int r, int ql, int qr)
{
    
    
    int mid = (l+r)>>1;
    if (ql <= l && r <= qr)
    {
    
    
        return tr[o].s;
    }
    if (tr[o].tag) pushdown(o);
    ll res = 0;
    if (ql <= mid)  res += querysum(ls,l,mid,ql,qr);
    if (mid < qr)   res += querysum(rs,mid+1,r,ql,qr);
    return res;
}
int main()
{
    
    
    IO;
    int T;
    cin >> T;
    while (T--)
    {
    
    
        cin >> n >> m;
        for (int i = 1; i <= n; i++)     cin >> a[i];
        build(1,1,n);
        for (int op,x,y,t, i = 1; i <= m; i++)
        {
    
    
            cin >> op >> x >> y;
            if (op == 0)
            {
    
    
                cin >> t;
                modify(1,1,n,x,y,t);
            }
            else if (op == 1)
            {
    
    
                cout << querymx(1,1,n,x,y) <<endl;
            }
            else
            {
    
    
                cout << querysum(1,1,n,x,y) << endl;
            }
        }
    }


    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43563956/article/details/107228316