AC日记——线段树练习三 codevs 1082 (分块尝试)

线段树练习 3

 

思路:

  分块;

 

来,上代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 200005
#define ll long long

ll n,m,flag[maxn],size,bel[maxn],dis[maxn];
ll sum[maxn],li[maxn],ri[maxn],blo,si[maxn];

inline void in(ll &now)
{
    ll if_z=1;now=0;
    char Cget=getchar();
    while(Cget>'9'||Cget<'0')
    {
        if(Cget=='-') if_z=-1;
        Cget=getchar();
    }
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
    now*=if_z;
}

int main()
{
    in(n),size=sqrt(n);ll pos=0,x;
    for(ll i=1;i<=n;i++)
    {
        in(dis[i]);
        if(pos==0) li[++blo]=i;
        pos++,sum[blo]+=dis[i],bel[i]=blo;
        if(pos==size) pos=0,ri[blo]=i;
    }
    ri[blo]=n;
    for(ll i=1;i<=blo;i++) si[i]=ri[i]-li[i]+1;
    ll ty,l,r;in(m);
    while(m--)
    {
        in(ty),in(l),in(r);
        if(ty==1)
        {
            in(x);
            for(ll i=bel[l];i<=bel[r];i++)
            {
                if(l<=li[i]&&r>=ri[i]) flag[i]+=x,sum[i]+=si[i]*x;
                else
                {
                    for(ll j=max(l,li[i]);j<=min(r,ri[i]);j++) dis[j]+=x,sum[i]+=x;
                }
            }
        }
        else
        {
            ll ans=0;
            for(ll i=bel[l];i<=bel[r];i++)
            {
                if(l<=li[i]&&r>=ri[i]) ans+=sum[i];
                else for(ll j=max(li[i],l);j<=min(ri[i],r);j++) ans+=dis[j]+flag[i];
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

posted @ 2017-04-21 11:49  IIIIIIIIIU  阅读(258)  评论(0编辑  收藏  举报