势能线段树
Segment tree Beats
待完善。
#include <cstdio>
#include <cctype>
#include <algorithm>
#pragma GCC diagnostic error "-std=gnu++11"
#define reg register
using namespace std;
namespace fast_IO {
template <typename conv>
inline conv read(conv &x) {
char ch=getchar(); int flag=1; x=0;
while (!isdigit(ch)) {if (ch=='-') flag=-flag; ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-48; ch=getchar();}
x*=flag;
}
template <typename conv, typename ... Args>
inline conv read(conv &first, Args & ... args) {
read(first);
read(args...);
}
template <typename conv>
inline conv write(conv x) {
if (x<0) {putchar('-'); x=-x;}
if (x>9) {write(x/10);}
putchar(x%10+48);
}
template <typename conv, typename ... Args>
inline conv write(conv first, Args ... args) {
write(first);
write(args...);
}
}
using namespace fast_IO;
const int maxn=1e6+5, inf=1<<30;
int n, m;
int a[maxn];
struct segment {
int left, right, length;
int sum;
int max, second_max, times_max;
/*maximum, second maximum & the number of times the minimum occurs*/
int min, second_min, times_min;
/*minimum, second minimum & the number of times the minimum occurs*/
int tag; /*addition*/
#define len length
#define nd_max second_max
#define nd_min second_min
#define T_max times_max
#define T_min times_min
} tree[maxn<<2];
#define L left
#define R right
#define L_son left_son
#define R_son right_son
#define mid middle
#define val value
#define res result
void push_up(int now) {
int left_son=now*2, right_son=now*2+1;
tree[now].T_max=tree[now].T_min=0;
tree[now].sum=tree[L_son].sum+tree[R_son].sum;
tree[now].max=max(tree[L_son].max, tree[R_son].max);
tree[now].nd_max=max(tree[L_son].nd_max, tree[R_son].nd_max);
if (tree[L_son].max^tree[R_son].max) {
tree[now].nd_max=max(tree[now].nd_max, min(tree[L_son].max, tree[R_son].max));
}
if (tree[now].max==tree[L_son].max) {
tree[now].T_max+=tree[L_son].T_max;
}
if (tree[now].max==tree[R_son].max) {
tree[now].T_max+=tree[R_son].T_max;
}
tree[now].min=min(tree[L_son].min, tree[R_son].min);
tree[now].nd_min=min(tree[L_son].nd_min, tree[R_son].nd_min);
if (tree[L_son].min^tree[R_son].min) {
tree[now].nd_min=min(tree[now].nd_min, max(tree[L_son].min, tree[R_son].min));
}
if (tree[now].min==tree[L_son].min) {
tree[now].T_min+=tree[L_son].T_min;
}
if (tree[now].min==tree[R_son].min) {
tree[now].T_min+=tree[R_son].T_min;
}
}
void build(int now, int left, int right) {
tree[now].L=L; tree[now].R=R; tree[now].len=R-L+1;
if (L==R) {
tree[now].max=tree[now].min=tree[now].sum=a[L];
tree[now].T_max=tree[now].T_min=1;
tree[now].nd_max=-inf; tree[now].nd_min=inf;
return ;
}
int middle=(L+R)>>1;
int left_son=now*2 , right_son=now*2+1;
build(L_son, L, mid); build(R_son, mid+1, R);
push_up(now);
}
void push_down(int now) {
int lazy_tag=tree[now].tag;
tree[now].tag=0;
int left_son=now*2 , right_son=now*2+1;
if (lazy_tag) {
tree[L_son].sum+=tree[L_son].len*lazy_tag;
tree[L_son].tag+=lazy_tag;
if (tree[L_son].nd_max>-inf) {
tree[L_son].nd_max+=lazy_tag;
}
if (tree[L_son].nd_min<inf) {
tree[L_son].nd_min+=lazy_tag;
}
tree[R_son].sum+=tree[R_son].len*lazy_tag;
tree[R_son].tag+=lazy_tag;
if (tree[R_son].nd_max>-inf) {
tree[R_son].nd_max+=lazy_tag;
}
if (tree[R_son].nd_min<inf) {
tree[R_son].nd_min+=lazy_tag;
}
}
if (tree[L_son].min<tree[now].min && tree[now].min<tree[L_son].nd_min) {
tree[L_son].sum+=(tree[now].min-tree[L_son].min)*tree[L_son].T_min;
tree[L_son].min=tree[now].min;
tree[L_son].max=max(tree[now].min, tree[L_son].max);
if (tree[L_son].max==tree[L_son].min) {
tree[L_son].sum=tree[L_son].len*tree[now].min;
tree[L_son].T_min=tree[L_son].T_max=tree[L_son].len;
tree[L_son].nd_max=-inf; tree[L_son].nd_min=inf;
}
else {
tree[L_son].nd_max=max(tree[now].min, tree[L_son].nd_max);
}
}
if (tree[R_son].min<tree[now].min && tree[now].min<tree[R_son].nd_min) {
tree[R_son].sum+=(tree[now].min-tree[R_son].min)*tree[R_son].T_min;
tree[R_son].min=tree[now].min;
tree[R_son].max=max(tree[now].min, tree[R_son].max);
if (tree[R_son].max==tree[R_son].min) {
tree[R_son].sum=tree[R_son].len*tree[now].min;
tree[R_son].T_min=tree[R_son].T_max=tree[R_son].len;
tree[R_son].nd_max=-inf; tree[R_son].nd_min=inf;
}
else {
tree[R_son].nd_max=max(tree[now].min, tree[R_son].nd_max);
}
}
if (tree[L_son].nd_max<tree[now].max && tree[now].max<tree[L_son].max) {
tree[L_son].sum+=(tree[now].max-tree[L_son].max)*tree[L_son].T_max;
tree[L_son].max=tree[now].max;
tree[L_son].min=min(tree[now].max, tree[L_son].min);
if (tree[L_son].max==tree[L_son].min){
tree[L_son].sum=tree[L_son].len*tree[now].max;
tree[L_son].T_min=tree[L_son].T_max=tree[L_son].len;
tree[L_son].nd_max=-inf; tree[L_son].nd_min=inf;
}
else {
tree[L_son].nd_min=min(tree[now].max, tree[L_son].nd_min);
}
}
if (tree[R_son].nd_max<tree[now].max && tree[now].max<tree[R_son].max) {
tree[R_son].sum+=(tree[now].max-tree[R_son].max)*tree[R_son].T_max;
tree[R_son].max=tree[now].max;
tree[R_son].min=min(tree[now].max, tree[R_son].min);
if (tree[R_son].max==tree[R_son].min){
tree[R_son].sum=tree[R_son].len*tree[now].max;
tree[R_son].T_min=tree[R_son].T_max=tree[R_son].len;
tree[R_son].nd_max=-inf; tree[R_son].nd_min=inf;
}
else {
tree[R_son].nd_min=min(tree[now].max, tree[R_son].nd_min);
}
}
}
void maximize(int now, int left, int right, int value) {
if (tree[now].min>=val) {
return ;
}
if (L<=tree[now].L && tree[now].R<=R && val<tree[now].nd_min) {
tree[now].sum+=(val-tree[now].min)*tree[now].T_min;
tree[now].min=val;
tree[now].max=max(val, tree[now].max);
if (tree[now].max==tree[now].min) {
tree[now].sum=tree[now].len*val;
tree[now].T_min=tree[now].T_max=tree[now].len;
tree[now].nd_max=-inf; tree[now].nd_min=inf;
}
else {
tree[now].nd_max=max(val, tree[now].nd_max);
}
return ;
}
int middle=(tree[now].L+tree[now].R)>>1;
push_down(now);
int left_son=now*2 , right_son=now*2+1;
if (L<=mid) maximize(L_son, L, R, val);
if (R>mid) maximize(R_son, L, R, val);
push_up(now);
}
void minimize(int now, int left, int right, int value) {
if (tree[now].min>=val) {
return ;
}
if (L<=tree[now].L && tree[now].R<=R && val>tree[now].nd_max) {
tree[now].sum+=(val-tree[now].max)*tree[now].T_max;
tree[now].max=val;
tree[now].min=min(val, tree[now].min);
if (tree[now].max==tree[now].min){
tree[now].sum=tree[now].len*val;
tree[now].T_min=tree[now].T_max=tree[now].len;
tree[now].nd_max=-inf; tree[now].nd_min=inf;
}
else {
tree[now].nd_min=min(val, tree[now].nd_min);
}
return ;
}
int middle=(tree[now].L+tree[now].R)>>1;
push_down(now);
int left_son=now*2 , right_son=now*2+1;
if (L<=mid) minimize(L_son, L, R, val);
if (R>mid) minimize(R_son, L, R, val);
push_up(now);
}
void update(int now, int left, int right, int value){
if (!val) {
return ;
}
if (L<=tree[now].L && tree[now].R<=R) {
tree[now].sum+=tree[now].len*val;
tree[now].tag+=val;
tree[now].max+=val; tree[now].min+=val;
if (tree[now].nd_max>-inf) {
tree[now].nd_max+=val;
}
if (tree[now].nd_min<inf) {
tree[now].nd_min+=val;
}
return ;
}
int middle=(tree[now].L+tree[now].R)>>1;
push_down(now);
int left_son=now*2 , right_son=now*2+1;
if (L<=mid) {
update(L_son, L, R, val);
}
if (R>mid) {
update(R_son, L, R, val);
}
push_up(now);
}
int query(int now, int left, int right, int op) {
if (L<=tree[now].L && tree[now].R<=R){
if (op==4) {
return tree[now].sum;
}
else if (op==5) {
return tree[now].max;
}
else {
return tree[now].min;
}
}
int middle=(tree[now].L+tree[now].R)>>1;
int result=0;
push_down(now);
int left_son=now*2 , right_son=now*2+1;
if (op==4) {
if (L<=mid) {
res+=query(L_son, L, R, op);
}
if (R>mid) {
res+=query(R_son, L, R, op);
}
}
else if (op==5) {
res=-inf;
if (L<=mid) {
res=max(res, query(L_son, L, R, op));
}
if (R>mid) {
res=max(res, query(R_son, L, R, op));
}
}
else {
res=inf;
if (L<=mid) {
res=min(res, query(L_son, L, R, op));
}
if (R>mid) {
res=min(res, query(R_son, L, R, op));
}
}
push_up(now);
return res;
}
int main() {
read(n);
for (reg int i=1; i<=n; i++) read(a[i]);
build(1, 1, n);
read(m);
for (reg int i=1; i<=m; i++) {
int op, x, y, z;
read(op, x, y);
if (op<=3) {
read(z);
if (op==1) {
update(1, x, y, z);
}
if (op==2) {
maximize(1, x, y, z);
}
if (op==3) {
minimize(1, x, y, z);
}
}
else {
write(query(1, x, y, op)); putchar('\n');
}
}
return 0;
}

浙公网安备 33010602011771号