鉴于<线段树练习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;
}