<线段树系列4> codevs 4927 线段树练习5

鉴于<线段树练习4>我还没有打
所以
<线段树系列4>就变成了 线段树练习5 w(゚Д゚)w
没错就是这样 ┭┮﹏┭┮

—>题外话:调了两天才调好,忘了在下放标记时把儿子的flg标为1!!!!!

codevs 4927 线段树练习5

题目描述 Description

有n个数和5种操作
add a b c:把区间[a,b]内的所有数都增加c
set a b c:把区间[a,b]内的所有数都设为c
sum a b:查询区间[a,b]的区间和
max a b:查询区间[a,b]的最大值
min a b:查询区间[a,b]的最小值

输入描述 Input Description

第一行两个整数n,m,第二行n个整数表示这n个数的初始值
接下来m行操作,同题目描述

输出描述 Output Description

对于所有的sum、max、min询问,一行输出一个答案

样例输入 Sample Input

10 6
3 9 2 8 1 7 5 0 4 6
add 4 9 4
set 2 6 2
add 3 8 2
sum 2 10
max 1 7
min 3 6

样例输出 Sample Output

49
11
4

数据范围及提示 Data Size & Hint

答案在long long 范围内 n,m小于等于100000,大于1


区间修改,区间查询(sum,max,min)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
typedef long long ll;
using namespace std;

const ll inf=0x7fffffffffffffff,maxn=1e6+10;
ll N,M,aa,b,c;
string s;
ll a[maxn];
struct hh
{
    ll l,r;
    ll summ,maxn,minn;
    ll add;
    bool flg;
}tree[maxn<<2];

void Set_New(ll n)
{
    tree[n].summ=tree[n<<1].summ+tree[n<<1|1].summ;
    tree[n].maxn=max(tree[n<<1].maxn,tree[n<<1|1].maxn);
    tree[n].minn=min(tree[n<<1].minn,tree[n<<1|1].minn);
}
void Updata_set(ll n,ll x)
{
    tree[n].summ=x*(tree[n].r-tree[n].l+1);
    tree[n].maxn=x;
    tree[n].minn=x;
}
void Updata_sum(ll n,ll x)
{
    tree[n].summ+=x*(tree[n].r-tree[n].l+1);
    tree[n].maxn+=x;
    tree[n].minn+=x;
}
void Spread(ll n)
{
    ll x=tree[n].add;
    if(x)
    {
         if(tree[n].flg)
         {
             tree[n<<1].add=x;
             tree[n<<1].flg=1;//不要忘记修改儿子的flg!! 
             tree[n<<1|1].add=x;
             tree[n<<1|1].flg=1;//
             Updata_set(n<<1,x);
             Updata_set(n<<1|1,x);
             tree[n].add=tree[n].flg=0;
             return;
         }
         tree[n<<1].add+=x;
         tree[n<<1|1].add+=x;
         Updata_sum(n<<1,x);
         Updata_sum(n<<1|1,x);
         tree[n].add=0;
    }

}
ll Ask_sum(ll l,ll r,ll n)
{
    ll lx=tree[n].l;
    ll rx=tree[n].r;
    if(lx>=l&&rx<=r) return tree[n].summ;
    Spread(n);
    ll mid=(lx+rx)>>1;
    ll ans=0;
    if(l<=mid) ans+=Ask_sum(l,r,n<<1);
    if(r>mid) ans+=Ask_sum(l,r,n<<1|1);
    return ans;
}
ll Ask_max(ll l,ll r,ll n)
{
    ll lx=tree[n].l;
    ll rx=tree[n].r;
    if(lx>=l&&rx<=r) return tree[n].maxn;
    Spread(n);
    ll mid=(lx+rx)>>1;
    ll ans=-1*inf;
    if(l<=mid) ans=max(ans,Ask_max(l,r,n<<1));
    if(r>mid) ans=max(ans,Ask_max(l,r,n<<1|1));
    return ans;
}
ll Ask_min(ll l,ll r,ll n)
{
    ll lx=tree[n].l;
    ll rx=tree[n].r;
    if(lx>=l&&rx<=r) return tree[n].minn;
    Spread(n);
    ll mid=(lx+rx)>>1;
    ll ans=inf;
    if(l<=mid) ans=min(ans,Ask_min(l,r,n<<1));
    if(r>mid) ans=min(ans,Ask_min(l,r,n<<1|1));
    return ans;
}
void Set(ll l,ll r,ll x,ll n)
{
    ll lx=tree[n].l;
    ll rx=tree[n].r;
    if(lx>=l&&rx<=r)
    {
        tree[n].add=x;
        tree[n].flg=1;
        Updata_set(n,x);
        return;
    }
    Spread(n);
    ll mid=(lx+rx)>>1;
    if(l<=mid) Set(l,r,x,n<<1);
    if(r>mid) Set(l,r,x,n<<1|1);
    Set_New(n);
}
void Add(ll l,ll r,ll x,ll n)
{
    ll lx=tree[n].l;
    ll rx=tree[n].r;
    if(lx>=l&&rx<=r)
    {
        tree[n].add+=x;
        Updata_sum(n,x);
        return;
    } 
    Spread(n);
    ll mid=(lx+rx)>>1;
    if(l<=mid) Add(l,r,x,n<<1);
    if(r>mid) Add(l,r,x,n<<1|1);
    Set_New(n);
}
void Build(ll l,ll r,ll n)
{
    tree[n].l=l;
    tree[n].r=r;
    if(l==r)
    {
        tree[n].summ=a[l];
        tree[n].maxn=a[l];
        tree[n].minn=a[l];
        return;
    }
    ll mid=(l+r)>>1;
    Build(l,mid,n<<1);
    Build(mid+1,r,n<<1|1);
    Set_New(n);

}
int main()
{

    cin>>N>>M;
    for(ll i=1;i<=N;++i) cin>>a[i];
    Build(1,N,1);
    for(ll i=1;i<=M;++i)
    {
        cin>>s;
        if(s=="add") 
        {
            cin>>aa>>b>>c;
            Add(aa,b,c,1);
        }
        else if(s=="set")
        {
            cin>>aa>>b>>c;
            Set(aa,b,c,1);
        }
        else if(s=="sum") 
        {
            cin>>aa>>b;
            cout<<Ask_sum(aa,b,1)<<"\n";
        }
        else if(s=="max") 
        {
            cin>>aa>>b;
            cout<<Ask_max(aa,b,1)<<"\n";
        }
        else if(s=="min") 
        {
            cin>>aa>>b;
            cout<<Ask_min(aa,b,1)<<"\n";
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值