[Template] Mr. Ji line segment tree

ACM template


table of Contents

Maximum interval

Gorgeous Sequence

Interval maximum operation often uses the following methods

Line segment tree maintenance:

  • Maximum interval mx mxmx
  • Strictly second largest interval smx smxsmx
  • Interval sum sumsum
  • Maximum number of interval cnt cntcnt
  • Interval value most lazy marker lazy lazylazy

To achieve the minimum interval operation, consider the interval maintained by the u node, and proceed as follows

  • m x ≤ x mx\leq x mxx . Obviously this modification will not affect the interval maintained by this node, so exit directly.
  • s m x < x < m x smx<x<mx smx<x<m x , obviously this modification will only affect all the maximum values ​​in this interval, so you can directly update the interval and the maximum value of the interval according to the number of maximum values, mark the lazy mark and exit.
  • x < = s m x x<=smx x<=s m x cannot be updated directly, so the left and right subtrees are recursively.

For the time complexity, please directly refer to the 2016 National Training Team Paper of Teacher Ji (not very good~

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=998244353;
const int N=1000010;
// 快读
template <class T>
inline void read(T &res)
{
    
    
	res = 0; bool bo = 0; char c;
	while (((c = getchar()) < '0' || c > '9') && c != '-');
	if (c == '-') bo = 1; else res = c - 48;
	while ((c = getchar()) >= '0' && c <= '9')
		res = (res << 3) + (res << 1) + (c - 48);
	if (bo) res = ~res + 1;
}
struct node
{
    
    
    int l,r;
    ll mx,smx,sum;
    int cnt;
    ll lazy;
}tree[N<<2];
int n,m;
ll a[N];
void pushup(int u)
{
    
    
    tree[u].sum=tree[u<<1].sum+tree[u<<1|1].sum;
    if(tree[u<<1].mx>tree[u<<1|1].mx)
    {
    
    
        tree[u].mx=tree[u<<1].mx;
        tree[u].smx=max(tree[u<<1].smx,tree[u<<1|1].mx);
        tree[u].cnt=tree[u<<1].cnt;
    }
    else if(tree[u<<1].mx<tree[u<<1|1].mx)
    {
    
    
        tree[u].mx=tree[u<<1|1].mx;
        tree[u].smx=max(tree[u<<1|1].smx,tree[u<<1].mx);
        tree[u].cnt=tree[u<<1|1].cnt;
    }
    else 
    {
    
    
        tree[u].mx=tree[u<<1|1].mx;
        tree[u].smx=max(tree[u<<1].smx,tree[u<<1|1].smx);
        tree[u].cnt=tree[u<<1].cnt+tree[u<<1|1].cnt;
    }
}
void pushlazy(int u,ll x)
{
    
    
    if(tree[u].mx<=x) return; 
    tree[u].sum+=(x-tree[u].mx)*tree[u].cnt;
    tree[u].mx=tree[u].lazy=x;
}
void pushdown(int u)
{
    
    
    if(tree[u].lazy==-1) return;
    pushlazy(u<<1,tree[u].lazy),pushlazy(u<<1|1,tree[u].lazy);
    tree[u].lazy=-1;
}
void build(int u,int l,int r)
{
    
    
    tree[u]={
    
    l,r,0,-1,0,0,-1};
    
    if(l==r) 
    {
    
    
        tree[u].mx=tree[u].sum=a[l];
        tree[u].cnt=1;
        return;
    }
    int mid=l+r>>1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
    pushup(u);
}
void modify(int u,int l,int r,ll x)
{
    
    
    if(x>=tree[u].mx) return;
    if(tree[u].l>=l&&tree[u].r<=r&&tree[u].smx<x)
    {
    
    
        pushlazy(u,x);
        return;
    }
    pushdown(u);
    int mid=tree[u].l+tree[u].r>>1;
    if(l<=mid) modify(u<<1,l,r,x);
    if(r>mid) modify(u<<1|1,l,r,x);
    pushup(u);
    
}
ll qmax(int u,int l,int r)
{
    
    
    if(tree[u].l>=l&&tree[u].r<=r) return tree[u].mx;
    int mid=tree[u].r+tree[u].l>>1;
    pushdown(u);
    ll v=-1;
    if(l<=mid) v=max(v,qmax(u<<1,l,r));
    if(r>mid) v=max(v,qmax(u<<1|1,l,r));
    pushup(u);
    return v;
}
ll qsum(int u,int l,int r)
{
    
    
    if(tree[u].l>=l&&tree[u].r<=r) return tree[u].sum;
    int mid=tree[u].r+tree[u].l>>1;
    pushdown(u);
    ll v=0;
    if(l<=mid) v+=qsum(u<<1,l,r);
    if(r>mid) v+=qsum(u<<1|1,l,r);
    pushup(u);
    return v;
}
int main()
{
    
    
    //IO;
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
    
    
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        build(1,1,n);
        while(m--)
        {
    
    
            int op,l,r;
            scanf("%d%d%d",&op,&l,&r);
            if(op==0)
            {
    
    
                ll v;
                scanf("%lld",&v);
                modify(1,l,r,v);
            }
            else if(op==1)
                printf("%lld\n",qmax(1,l,r));
            else
                printf("%lld\n",qsum(1,l,r));
        }
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/Fighting_Peter/article/details/110247986