线段树专题

 Ayaya......好久没发博客了呢(笑..这几天大概算做了线段树的专题吧,以前的题里其实也有能用线段树吧,

但都没有去写,终于集中练了一下线段树。。总体来说线段树还是很好理解的,只是代码稍长了点,多用一用

背熟了就好了。

 这次专题是在COGS上练习的,其中有几道模板题,过了大概以后就能用了:

  单点修改区间查询:COGS 264 http://www.cogs.pro/cogs/problem/problem.php?pid=264

  区间修改单点查询:COGS 1316 http://www.cogs.pro/cogs/problem/problem.php?pid=1316

  区间修改区间查询:COGS 1317 http://www.cogs.pro/cogs/problem/problem.php?pid=1317

 下面附上线段树区间修改区间查询的代码

#include<cstdio>
#define ll long long
using namespace std;
ll n,m,y,u,z,tr[20010],la[20010];
char s[10];
ll re()
{
    ll x=0,c=getchar(),f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
void t(ll x,ll y,ll r)
{
    if(x==y)
    {
        tr[r]=re();
        return;
    }
    ll mid=(x+y)>>1;
    t(x,mid,r<<1);
    t(mid+1,y,(r<<1)+1);
    tr[r]=tr[r<<1]+tr[(r<<1)+1];
}
void down(ll rt,ll ln,ll rn){
    if(la[rt]){
        la[rt<<1]+=la[rt];
        la[rt<<1|1]+=la[rt];
        tr[rt<<1]+=la[rt]*ln;
        tr[rt<<1|1]+=la[rt]*rn;
        la[rt]=0;
    }
}
void d(ll x,ll b,ll y,ll r,ll u,ll l)
{
    if(x<=r&&u<=b)
    {
        tr[l]+=y*(u-r+1);
        la[l]+=y;
        return;
    }
    ll mid=(r+u)>>1;
    down(l,mid-r+1,u-mid);
    if(x<=mid)d(x,b,y,r,mid,l<<1);
    if(b>mid)d(x,b,y,mid+1,u,(l<<1)+1);
    tr[l]=tr[l<<1]+tr[(l<<1)+1];
}
ll q(ll x,ll y,ll r,ll u,ll l)
{
    if(x<=r&&y>=u)return tr[l];
    ll mid=(r+u)>>1,he=0;
    down(l,mid-r+1,u-mid);
    if(x<=mid)he+=q(x,y,r,mid,l<<1);
    if(y>mid)he+=q(x,y,mid+1,u,(l<<1)+1);
    return he;
}
int main()
{   
    //freopen("shuliec.in","r",stdin);freopen("shuliec.out","w",stdout);
    n=re();m=re();
    if(n==0)return 0;
    t(1,n,1);
    while(m--)
    {
        scanf("%s",&s);y=re();z=re();
        if(s[0]=='q')printf("%lld
",q(y,z,1,n,1));
        if(s[0]=='m')u=re(),d(y,z,u,1,n,1);
    }
}

   紫fhlaudhtaskhfkldjasyrue  

  

ほらあなたの描くこの世界は私を映しているよ---- 看呐 你所描绘出的这个世界里,映出了我的身影哟
原文地址:https://www.cnblogs.com/yukari17/p/7197362.html