总之就是 | 洛谷 P1253 [yLOI2018] 扶苏的问题

单纯的和洛谷博客同步一下。

「思路简述」

一道比较板的线段树吧,比较适合新手拿来练手。

题意非常清楚了,简单来说就是需要一种支持区间查询和区间修改的数据结构,那么很自然的就能想到用线段树来解决。

因为有两种区间修改的操作,所以我们需要两个 Tag,下传的操作和正常的区间加没有太多区别,只不过需要注意在下传时,要先传 Cover 操作再下传 Add 操作。

「Code」

因为每次操作的 \(x \le 10^9\),所以注意要开 long longINF 值的大小。

前面的学长提供了指针的写法,我这里则是相对普通的数组写法。

#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cstring>

#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define Heriko return
#define Deltana 0
#define Romanno 1
#define S signed
#define LL long long
#define R register
#define I inline
#define CI const int
#define mst(a, b) memset(a, b, sizeof(a))
#define ON std::ios::sync_with_stdio(false);cin.tie(0)
#define Files() freopen("RNMTQ.in","r",stdin);freopen("RNMTQ.out","w",stdout)

using namespace std;

template<typename J>
I void fr(J &x)
{
    short f(1);x=0;char c=getchar();

    while(c<'0' or c>'9')
    {
        if(c=='-') f=-1;
        
        c=getchar();
    }

    while (c>='0' and c<='9') 
    {
        x=(x<<3)+(x<<1)+(c^=48);
        c=getchar();
    }
   
    x*=f;
}

template<typename J>
I void fw(J x,bool k)
{
    if(x<0) x=-x,putchar('-');

    static short stak[35];short top(0);

    do
    {
        stak[top++]=x%10;
        x/=10;
    }
    while(x);
    while(top) putchar(stak[--top]+'0');

    k?puts(""):putchar(' ');
}

template<typename J>
I J Hmax(const J &x,const J &y) {Heriko x>y?x:y;}

const LL MXX(1e6+1),INF(1e12);

int n,q;

struct Node
{
    int l,r;LL mx,tg1,tg2;
}

t[MXX<<2];

I void Pushup(int x) {t[x].mx=Hmax(t[lc(x)].mx,t[rc(x)].mx);}

I void Pushdown(int x)
{
    if(t[x].tg2!=INF)
    {
        t[lc(x)].tg1=0;
        t[lc(x)].tg2=t[x].tg2;
        t[lc(x)].mx=t[x].tg2;
        t[rc(x)].tg1=0;
        t[rc(x)].tg2=t[x].tg2;
        t[rc(x)].mx=t[x].tg2;
        t[x].tg2=INF;
    }

    if(t[x].tg1)
    {
        t[lc(x)].tg1+=t[x].tg1;
        t[lc(x)].mx+=t[x].tg1;
        t[rc(x)].tg1+=t[x].tg1;
        t[rc(x)].mx+=t[x].tg1;
        t[x].tg1=0;
    }
}

void Build(int x,int l,int r)
{
    t[x].l=l,t[x].r=r;t[x].mx=t[x].tg1=0;t[x].tg2=INF;

    if(l==r)
    {
        fr(t[x].mx);

        Heriko;
    }

    int mid((l+r)>>1);
    Build(lc(x),l,mid);Build(rc(x),mid+1,r);
    Pushup(x);
}

void ModifyAdd(int x,int lx,int rx,LL v)
{
    if(lx<=t[x].l and t[x].r<=rx)
    {
        t[x].tg1+=v;t[x].mx+=v;

        Heriko;
    }

    Pushdown(x);
    int mid((t[x].l+t[x].r)>>1);

    if(lx<=mid) ModifyAdd(lc(x),lx,rx,v);
    
    if(rx>mid) ModifyAdd(rc(x),lx,rx,v);

    Pushup(x);
}

void ModifyChange(int x,int lx,int rx,LL v)
{
    if(lx<=t[x].l and t[x].r<=rx)
    {
        t[x].tg1=0;t[x].tg2=v;t[x].mx=v;

        Heriko;
    }

    Pushdown(x);
    int mid((t[x].l+t[x].r)>>1);

    if(lx<=mid) ModifyChange(lc(x),lx,rx,v);
    
    if(rx>mid) ModifyChange(rc(x),lx,rx,v);

    Pushup(x);
}

LL Query(int x,int lx,int rx)
{
    if(lx<=t[x].l and t[x].r<=rx) Heriko t[x].mx;

    LL res(-INF);int mid((t[x].l+t[x].r)>>1);

    Pushdown(x);

    if(lx<=mid) res=Hmax(Query(lc(x),lx,rx),res);
    
    if(rx>mid) res=Hmax(Query(rc(x),lx,rx),res);

    Heriko res;
}

S main()
{
    fr(n),fr(q);Build(1,1,n);

    while(q--)
    {
        int opt,l,r;LL x;
        fr(opt),fr(l),fr(r);

        if(opt==1) fr(x),ModifyChange(1,l,r,x);
        else if(opt==2) fr(x),ModifyAdd(1,l,r,x);
        else fw(Query(1,l,r),1);
    }
    
    Heriko Deltana;
}

如有错误之处请各位大佬及时指出。

posted @ 2021-10-26 15:33  HerikoDeltana  阅读(83)  评论(0编辑  收藏  举报