【刷题】【线段树】

(1)Laz标记:

题目:区区区间

区区区间 (nowcoder.com)

题解摘自:区区区间 _牛客博客 (nowcoder.net)

  我们发现这个等差数列的等差为1。对于修改一段区间l-rlr如果我们知道首项值,那么我们便可以在O(1)O(1)的时间复杂度计算出这段区间的大小。

  又可以知道,对于线段树每一个结点,代表一段区间,那么我们我们用lazy数组保存这一段区间的首项,那么我们便可以在O(1)的时间复杂度内算出这一段区间的值。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int n,m;
const int N=1e6+10;
int d[N];

int root,cnt;
struct node
{
    int lson,rson;
    ll sum; int len;
    int laz;            //这里的k表示首项 
}tr[N<<2];

void update(int rt)
{
    int ls = tr[rt].lson ,rs = tr[rt].rson ;
    tr[rt].sum = tr[ls].sum + tr[rs].sum ;
}

void build(int & rt,int l,int r)
{
    rt=++cnt;
    tr[rt].len = r-l+1;
    if(l==r)
    {
        tr[rt].sum = d[l];
        return ;
    }
    
    int mid=(l+r)>>1;
    build(tr[rt].lson ,l,mid);
    build(tr[rt].rson ,mid+1,r);
    update(rt);
}

ll get_sum(int rt,int laz,int len)
{
    return 1LL*(laz + laz+len-1)*len/2;
}

void push_down(int rt,int l,int mid)
{
    int ls = tr[rt].lson ,rs = tr[rt].rson ;
    int v=tr[rt].laz; tr[rt].laz = 0;
    tr[ls].laz = v , tr[rs].laz = v+mid-l+1 ;
    tr[ls].sum = get_sum(ls,tr[ls].laz ,tr[ls].len ) , tr[rs].sum = get_sum(rs,tr[rs].laz ,tr[rs].len ) ;
}

int ql,qr,qv;
void change(int rt,int l,int r) //给ql到qr区间上,加上qv 
{
    if(ql<=l && r<=qr )
    {
        int fst=qv+l-ql;
        tr[rt].laz = fst;
        tr[rt].sum = get_sum(rt,tr[rt].laz,tr[rt].len);
        return ;
    }
    
    int mid=(l+r)>>1;
    if(tr[rt].laz ) push_down(rt,l,mid);
    if(qr<=mid ) change(tr[rt].lson ,l,mid);
    else if(mid<ql ) change(tr[rt].rson ,mid+1,r);
    else 
        change(tr[rt].lson ,l,mid),
        change(tr[rt].rson ,mid+1,r);
    update(rt);
}

ll query(int rt,int l,int r)
{
    if(ql<=l && r<=qr )
        return tr[rt].sum;
    
    int mid=(l+r)>>1;
    if(tr[rt].laz ) push_down(rt,l,mid);
    if(qr<=mid ) return query(tr[rt].lson ,l,mid);
    else if(mid<ql ) return query(tr[rt].rson ,mid+1,r);
    else 
        return query(tr[rt].lson ,l,mid) + query(tr[rt].rson ,mid+1,r);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&d[i]);
    build(root,1,n);
    
    int op,a,b,c;
    while(m--)
    {
        scanf("%d%d%d",&op,&a,&b);
        if(op==1)
        {
            scanf("%d",&qv);
            ql=a,qr=b;
            change(root,1,n);
        }
        else
        {
            ql=a,qr=b;
            printf("%lld\n",query(root,1,n));
        }
    }
    
    return 0;
} 
View Code

 

(2)

 

posted @ 2022-09-19 00:10  心若笺诗  阅读(13)  评论(0编辑  收藏  举报