【テンプレート】線分樹_区間の最大値、区間の合計、修正
7658 ワード
コードは以下のとおりです
お天気はいかがですかω⁄•⁄ ⁄)⁄ 以上
#include
#include
#include
#include
#define L(x) (x << 1)//
#define R(x) (x << 1 | 1)//
#define sz(x) (tree[x].r - tree[x].l + 1)//
using namespace std;
typedef long long ll;
const ll MAXN = 200005;
ll n,m,a,b,c,num[MAXN];
string t;
// l == ;r == ;p == now;
struct tree{
ll l,r,add,sum;//
ll min,max;//
}tree[MAXN << 2];
// p == now
void update(ll p){
tree[p].sum = tree[L(p)].sum + tree[R(p)].sum;
tree[p].max = max(tree[L(p)].max,tree[R(p)].max);
tree[p].min = min(tree[L(p)].min,tree[R(p)].min);
}
void spread(ll p){
if(!tree[p].add) return;
tree[L(p)].max += tree[p].add;
tree[R(p)].max += tree[p].add;
tree[L(p)].min += tree[p].add;
tree[R(p)].min += tree[p].add;
tree[L(p)].add += tree[p].add;
tree[R(p)].add += tree[p].add;
tree[L(p)].sum += tree[p].add * sz(L(p));
tree[R(p)].sum += tree[p].add * sz(R(p));
tree[p].add = 0;//!!!!!!!
update(p);
}
//
void build(ll l,ll r,ll p){
tree[p].l = l,tree[p].r = r;
if(l == r){
tree[p].min = tree[p].max = tree[p].sum = num[l];
return;
}
ll mid = (tree[p].l + tree[p].r) >> 1;
build(l,mid,L(p)); build(mid + 1,r,R(p));
update(p);
}
//
void change(ll l,ll r,ll p,ll v){
if(l <= tree[p].l && tree[p].r <= r){
tree[p].add += v;
tree[p].min += v;
tree[p].max += v;
tree[p].sum += v * sz(p);
return;
}
spread(p);
ll mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) change(l,r,L(p),v);
if(mid < r) change(l,r,R(p),v);
update(p);
}
//
ll ask_sum(ll l,ll r,ll p){
if(l <= tree[p].l && tree[p].r <= r)
return tree[p].sum;
spread(p);
ll ans = 0,mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) ans += ask_sum(l,r,L(p));
if(mid < r) ans += ask_sum(l,r,R(p));
update(p); return ans;
}
//
ll ask_max(ll l,ll r,ll p){
if(l <= tree[p].l && tree[p].r <= r)
return tree[p].max;
spread(p);
ll ans = 0,mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) ans = max(ans,ask_max(l,r,L(p)));
if(mid < r) ans = max(ans,ask_max(l,r,R(p)));
update(p); return ans;
}
//
ll ask_min(ll l,ll r,ll p){
if(l <= tree[p].l && tree[p].r <= r)
return tree[p].min;
spread(p);
ll ans = 2333333,mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) ans = min(ans,ask_min(l,r,L(p)));
if(mid < r) ans = min(ans,ask_min(l,r,R(p)));
update(p); return ans;
}
int main(){
memset(num,0,sizeof(num));
scanf("%lld",&n);
for(ll i = 1; i <= n; i ++)
scanf("%lld",&num[i]);
build(1,n,1); scanf("%lld",&m);
for(ll i = 1; i <= m; i ++){
cin >> t;
if(t == "add"){
scanf("%lld %lld %lld",&a,&b,&c);
change(a,b,1,c);
}
else if(t == "sum"){
scanf("%lld %lld",&a,&b);
printf("%lld
",ask_sum(a,b,1));
}
else if(t == "max"){
scanf("%lld %lld",&a,&b);
printf("%lld
",ask_max(a,b,1));
}
else if(t == "min"){
scanf("%lld %lld",&a,&b);
printf("%lld
",ask_min(a,b,1));
}
}
return 0;
}
QQはこのような意味で、下记の処理に注意します.お天気はいかがですかω⁄•⁄ ⁄)⁄ 以上