[Modelo] Árvore de segmento de linha do Sr. Ji

Modelo ACM


Intervalo máximo

Sequência linda

A operação máxima do intervalo geralmente usa os seguintes métodos

Manutenção da árvore do segmento de linha:

  • Intervalo máximo mx mxm x
  • Estritamente segundo maior intervalo smx smxs m x
  • Soma da soma do intervalos u m
  • Número máximo de intervalo cnt cntc n t
  • Intervalo valor mais preguiçoso marcador preguiçoso preguiçosol a z y

Para atingir a operação de intervalo mínimo, considere o intervalo mantido pelo nó u e proceda da seguinte forma

  • mx ≤ x mx \ leq xm xx . Obviamente, esta modificação não afetará o intervalo mantido por este nó, então saia diretamente.
  • smx <x <mx smx <x <mxs m x<x<m x , obviamente esta modificação afetará apenas todos os valores máximos neste intervalo, então você pode atualizar diretamente o intervalo e o valor máximo do intervalo de acordo com o número de valores máximos, marcar a marca preguiçosa e sair.
  • x <= smx x <= smxx<=s m x não pode ser atualizado diretamente, portanto, as subárvores esquerda e direita são recursivamente.

Para a complexidade do tempo, consulte diretamente o Documento da Equipe Nacional de Treinamento de 2016 do Professor Ji (não muito bom ~

#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;
}

Acho que você gosta

Origin blog.csdn.net/Fighting_Peter/article/details/110247986
Recomendado
Clasificación