P1438 无聊的数列 (线段树)

题目链接


Solution

直接维护一个差分的线段树就好了.
其中线段树的节点代表 (r)(l) 多多少.

Code

#include<bits/stdc++.h>
#define ll long long
#define mid (l+r)/2
using namespace std;
const int maxn=100008;
ll sgm[maxn*4],lazy[maxn*4];
ll n,w[maxn],m;

void push_down(int node,int l,int r)
{
    sgm[node*2]+=lazy[node]*(mid-l+1);
    sgm[node*2+1]+=lazy[node]*(r-mid);
    lazy[node*2]+=lazy[node];
    lazy[node*2+1]+=lazy[node];
    lazy[node]=0;
}

void build(int node,int l,int r)
{
     if(l==r){sgm[node]=w[l]-w[l-1];return;}
     build(node*2,l,mid);
     build(node*2+1,mid+1,r);
     sgm[node]=sgm[node*2]+sgm[node*2+1];
}

void change(int node,int l,int r,int L,int R,ll v)
{
      if(l>R||r<L)return;
      if(l>=L&&r<=R)
      {lazy[node]+=v; sgm[node]+=(r-l+1)*v;return;}
      push_down(node,l,r);
      change(node*2,l,mid,L,R,v);
      change(node*2+1,mid+1,r,L,R,v);
      sgm[node]=sgm[node*2]+sgm[node*2+1];
}

ll query(int node,int l,int r,int L,int R)
{
      if(l>R||r<L)return 0;
      if(l>=L&&r<=R)
      return sgm[node];
      push_down(node,l,r);
      return query(node*2,l,mid,L,R)+query(node*2+1,mid+1,r,L,R);
}

ll read()
{
    char ch=getchar(); ll f=1,w=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
    return f*w;
}

int main()
{
    n=read(); m=read();
    for(int i=1;i<=n;i++)
    w[i]=read();
    build(1,1,n);
    while(m--)
    {
        ll opt=read();
        ll x,y,v,d;
        if(opt==2)
        x=read(),
        cout<<query(1,1,n,1,x)<<endl;
        else
        {
            x=read(); y=read();
            v=read(); d=read();
            change(1,1,n,x,x,v);
            change(1,1,n,x+1,y,d);
            change(1,1,n,y+1,y+1,-(v+(y-x)*d));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Kv-Stalin/p/9592522.html