洛谷 2846 (线段树)

/*
如果是查询[2,4] 就是a2+a3+a4 a2+a3 a2
显然裸地线段树算不出来
我们维护前缀和 那查询的时候还要减去前多计算的 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010
#define ll long long
using namespace std;
ll n,m,tot,a[maxn],s[maxn],x,y,z;
struct node
{
    ll l,r,lc,rc,lazy,sum;
}t[maxn*4];
ll init()
{
    ll x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
void Build(ll li,ll ri)
{
    ll k=++tot;
    t[k].l=li;t[k].r=ri;
    if(li==ri-1)
      {
          t[k].sum=s[li];return;
      }
    ll mid=(li+ri)/2;
    t[k].lc=tot+1;Build(li,mid);
    t[k].rc=tot+1;Build(mid,ri);
    t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum;
}
void Updata(int k)
{
    t[t[k].lc].lazy+=t[k].lazy;
    t[t[k].rc].lazy+=t[k].lazy;
    t[t[k].lc].sum+=(t[t[k].lc].r-t[t[k].lc].l)*t[k].lazy;
    t[t[k].rc].sum+=(t[t[k].rc].r-t[t[k].rc].l)*t[k].lazy;
    t[k].lazy=0;
}
void Change(ll k,ll li,ll ri,ll data)
{
    if(li<=t[k].l&&ri>=t[k].r)
      {
          t[k].sum+=(t[k].r-t[k].l)*data;
          t[k].lazy+=data;
          return;
      }
    if(t[k].lazy)Updata(k);
    ll mid=(t[k].l+t[k].r)/2;
    if(li<mid)Change(t[k].lc,li,ri,data);
    if(ri>mid)Change(t[k].rc,li,ri,data);
    t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum;
}
ll Query(int k,int li,int ri)
{
    if(li<=t[k].l&&ri>=t[k].r)return t[k].sum;
    ll r=0;
    if(t[k].lazy)Updata(k);
    ll mid=(t[k].l+t[k].r)/2;
    if(li<mid)r+=Query(t[k].lc,li,ri);
    if(ri>mid)r+=Query(t[k].rc,li,ri);
    return r;
}
int main()
{
    n=init();m=init();
    for(int i=1;i<=n;i++)
      a[i]=init();
    for(int i=1;i<=n;i++)
      s[i]=s[i-1]+a[i];
    Build(1,n+1);
    for(int i=1;i<=m;i++)
      {
          x=init();y=init();z=init();
          if(x==1)Change(1,y,n+1,z);
          if(x==2)printf("%lld\n",Query(1,y,z+1)-(z-y+1)*Query(1,y-1,y));
      }
    return 0;
}

 

posted @ 2016-08-29 19:28  一入OI深似海  阅读(171)  评论(0编辑  收藏  举报