[線段樹 區間最值操作 模板 Segment tree Beats!] BZOJ 4695 最假女選手
阿新 • • 發佈:2019-02-11
鬼畜線段樹的大模板題 具體見吉麗的集訓隊論文
我終於會寫線段樹了 不對 我好像還不會歷史最值
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=500005;
const int M=N<<2;
int mx[M],sx[M],cx[M],mn[M],sn[M],cn[M]; ll sum[M]; int ta[M];
inline void update(int x){
int l=x<<1,r=x<<1|1;
sum[x]=sum[l]+sum[r];
if (mx[l]==mx[r])
mx[x]=mx[l],cx[x]=cx[l]+cx[r],sx[x]=max(sx[l],sx[r]);
else{ // r>l
if (mx[l]>mx[r]) swap(l,r);
mx[x]=mx[r]; cx[x]=cx[r];
sx[x]=max(sx[r],mx[l]);
}
if (mn[l]==mn[r])
mn[x]=mn[l],cn[x]=cn[l]+cn[r],sn[x]=min(sn[l],sn[r]);
else { // r<l
if (mn[l]<mn[r]) swap(l,r);
mn[x]=mn[r]; cn[x]=cn[r];
sn[x]=min(sn[r],mn[l]);
}
}
inline void Build(int x,int l,int r){
if (l==r){
int a; read(a);
sum[x]=mx[x]=mn[x]=a; cx[x]=cn[x]=1; sx[x]=-1<<30; sn[x]=1<<30; ta[x]=0;
return;
}
int mid=(l+r)>>1; Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
update(x);
}
inline void _add(int x,int l,int r,int t){
sum[x]+=(ll)(r-l+1)*t;
mn[x]+=t; sn[x]+=t; mx[x]+=t; sx[x]+=t;
ta[x]+=t;
}
inline void _min(int x,int l,int r,int t){
sum[x]-=(ll)cx[x]*(mx[x]-t);
mx[x]=t; mn[x]=min(mn[x],t);
if (mn[x]==mx[x]){
sum[x]=(ll)(r-l+1)*t; cx[x]=cn[x]=r-l+1; sx[x]=-1<<30; sn[x]=1<<30;
}else
sn[x]=min(sn[x],t);
}
inline void _max(int x,int l,int r,int t){
sum[x]+=(ll)cn[x]*(t-mn[x]);
mn[x]=t; mx[x]=max(mx[x],t);
if (mn[x]==mx[x]){
sum[x]=(ll)(r-l+1)*t; cx[x]=cn[x]=r-l+1; sx[x]=-1<<30; sn[x]=1<<30;
}else
sx[x]=max(sx[x],t);
}
inline void push(int x,int l,int r){
int mid=(l+r)>>1;
if (ta[x]){
_add(x<<1,l,mid,ta[x]);
_add(x<<1|1,mid+1,r,ta[x]);
ta[x]=0;
}
if (mx[x<<1]>mx[x] && sx[x<<1]<mx[x]) _min(x<<1,l,mid,mx[x]);
if (mx[x<<1|1]>mx[x] && sx[x<<1|1]<mx[x]) _min(x<<1|1,mid+1,r,mx[x]);
if (mn[x<<1]<mn[x] && sn[x<<1]>mn[x]) _max(x<<1,l,mid,mn[x]);
if (mn[x<<1|1]<mn[x] && sn[x<<1|1]>mn[x]) _max(x<<1|1,mid+1,r,mn[x]);
}
int ql,qr,qt;
inline void Mmax(int x,int l,int r){
if (mn[x]>=qt) return;
if (ql<=l && r<=qr && qt<sn[x]){
_max(x,l,r,qt); return;
}
push(x,l,r); int mid=(l+r)>>1;
if (ql<=mid) Mmax(x<<1,l,mid);
if (qr>mid) Mmax(x<<1|1,mid+1,r);
update(x);
}
inline void Mmin(int x,int l,int r){
if (mx[x]<=qt) return;
if (ql<=l && r<=qr && qt>sx[x]){
_min(x,l,r,qt); return;
}
push(x,l,r); int mid=(l+r)>>1;
if (ql<=mid) Mmin(x<<1,l,mid);
if (qr>mid) Mmin(x<<1|1,mid+1,r);
update(x);
}
inline void Add(int x,int l,int r){
if (ql<=l && r<=qr){
_add(x,l,r,qt); return;
}
push(x,l,r); int mid=(l+r)>>1;
if (ql<=mid) Add(x<<1,l,mid);
if (qr>mid) Add(x<<1|1,mid+1,r);
update(x);
}
inline int Max(int x,int l,int r){
if (ql<=l && r<=qr) return mx[x];
push(x,l,r);
int ret=-1<<30; int mid=(l+r)>>1;
if (ql<=mid) ret=max(ret,Max(x<<1,l,mid));
if (qr>mid) ret=max(ret,Max(x<<1|1,mid+1,r));
return ret;
}
inline int Min(int x,int l,int r){
if (ql<=l && r<=qr) return mn[x];
push(x,l,r);
int ret=1<<30; int mid=(l+r)>>1;
if (ql<=mid) ret=min(ret,Min(x<<1,l,mid));
if (qr>mid) ret=min(ret,Min(x<<1|1,mid+1,r));
return ret;
}
inline ll Sum(int x,int l,int r){
if (ql<=l && r<=qr) return sum[x];
push(x,l,r);
ll ret=0; int mid=(l+r)>>1;
if (ql<=mid) ret+=Sum(x<<1,l,mid);
if (qr>mid) ret+=Sum(x<<1|1,mid+1,r);
return ret;
}
int n;
int main(){
int Q,order,t;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); Build(1,1,n);
read(Q);
while (Q--){
read(order); read(ql); read(qr);
if (order==1){
read(qt),Add(1,1,n);
}else if (order==2){
read(qt),Mmax(1,1,n);
}else if (order==3){
read(qt),Mmin(1,1,n);
}else if (order==4){
printf("%lld\n",Sum(1,1,n));
}else if (order==5){
printf("%d\n",Max(1,1,n));
}else if (order==6){
printf("%d\n",Min(1,1,n));
}
}
return 0;
}