[bzoj4695] 最假女选手
Description
在刚刚结束的水题嘉年华的压轴节目放水大赛中,wyywyy如愿以偿的得到了最假女选手的奖项。但是作为主办人的
C_SUNSHINE为了证明wyywyy确实在放水,决定出一道基础题考察wyywyy的姿势水平。给定一个长度为 N序列,编号
从1 到 N。要求支持下面几种操作:
1.给一个区间[L,R] 加上一个数x
2.把一个区间[L,R] 里小于x 的数变成x
3.把一个区间[L,R] 里大于x 的数变成x
4.求区间[L,R] 的和
5.求区间[L,R] 的最大值
6.求区间[L,R] 的最小值
Input
第一行一个整数 N表示序列长度。
第二行N 个整数Ai 表示初始序列。
第三行一个整数M 表示操作个数。
接下来M 行,每行三或四个整数,第一个整数Tp 表示操作类型,接下来L,R,X 或L,R 表述操作数。
1<=tp<=6,N,M<=5*105,|Ai|<=108
Tp=1时,|x|<=1000
Tp=2或3时,|x|<=10^8
Output
对于每个4,5,6类型的操作输出一行一个整数表示答案。
Sample Input
2
1 2
2
2 1 2 2
4 1 2
Sample Output
4
Solution
吉司机线段树模板题。
记下最大值次大值,能改就改,否则大力dfs,复杂度\(O(m\log^2 n)\)。
细节挺多的,注意int不要爆了。
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
template <typename T> void print(T x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
template <typename T> void write(T x) {if(!x) putchar('0');else print(x);putchar('\n');}
const int maxn = 2e6+10;
const int inf = 2e9;
int n,m;
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
struct Segment_Tree {
int mx[maxn],smx[maxn],mn[maxn],smn[maxn],cntmx[maxn],cntmn[maxn],tag[maxn];
ll sum[maxn];
void update(int p) {
sum[p]=sum[ls]+sum[rs];
if(mx[ls]==mx[rs]) mx[p]=mx[ls],smx[p]=max(smx[ls],smx[rs]),cntmx[p]=cntmx[ls]+cntmx[rs];
else if(mx[ls]<mx[rs]) mx[p]=mx[rs],smx[p]=max(smx[rs],mx[ls]),cntmx[p]=cntmx[rs];
else mx[p]=mx[ls],smx[p]=max(smx[ls],mx[rs]),cntmx[p]=cntmx[ls];
if(mn[ls]==mn[rs]) mn[p]=mn[ls],smn[p]=min(smn[ls],smn[rs]),cntmn[p]=cntmn[ls]+cntmn[rs];
else if(mn[ls]>mn[rs]) mn[p]=mn[rs],smn[p]=min(smn[rs],mn[ls]),cntmn[p]=cntmn[rs];
else mn[p]=mn[ls],smn[p]=min(smn[ls],mn[rs]),cntmn[p]=cntmn[ls];
}
void push_tag(int p,int l,int r,int x) {
tag[p]+=x,sum[p]+=1ll*(r-l+1)*x,mn[p]+=x,mx[p]+=x;
if(smn[p]!=inf) smn[p]+=x;
if(smx[p]!=-inf) smx[p]+=x;
}
void push_max(int p,int l,int r,int x) {
sum[p]=sum[p]-1ll*cntmx[p]*(mx[p]-x),mx[p]=x,mn[p]=min(mn[p],x);
if(mx[p]==mn[p]) {
int t=r-l+1;
cntmx[p]=cntmn[p]=t;sum[p]=1ll*mx[p]*t;
smx[p]=-inf,smn[p]=inf;
}else smn[p]=min(smn[p],x);
}
void push_min(int p,int l,int r,int x) {
sum[p]=sum[p]-1ll*cntmn[p]*(mn[p]-x),mn[p]=x,mx[p]=max(mx[p],x);
if(mx[p]==mn[p]) {
int t=r-l+1;
cntmx[p]=cntmn[p]=t;sum[p]=1ll*mx[p]*t;
smx[p]=-inf,smn[p]=inf;
}else smx[p]=max(smx[p],x);
}
void pushdown(int p,int l,int r) {
if(tag[p]) push_tag(ls,l,mid,tag[p]),push_tag(rs,mid+1,r,tag[p]),tag[p]=0;
if(mx[ls]>mx[p]&&mx[p]>smx[ls]) push_max(ls,l,mid,mx[p]);
if(mx[rs]>mx[p]&&mx[p]>smx[rs]) push_max(rs,mid+1,r,mx[p]);
if(mn[ls]<mn[p]&&mn[p]<smn[ls]) push_min(ls,l,mid,mn[p]);
if(mn[rs]<mn[p]&&mn[p]<smn[rs]) push_min(rs,mid+1,r,mn[p]);
}
void modify_add(int p,int l,int r,int x,int y,int z) {
if(x<=l&&r<=y) return push_tag(p,l,r,z),void();
pushdown(p,l,r);
if(x<=mid) modify_add(ls,l,mid,x,y,z);
if(y>mid) modify_add(rs,mid+1,r,x,y,z);
update(p);
}
void modify_max(int p,int l,int r,int x,int y,int z) {
if(z<=mn[p]) return ;
if(x<=l&&r<=y&&z<smn[p]) return push_min(p,l,r,z),void();
pushdown(p,l,r);
if(x<=mid) modify_max(ls,l,mid,x,y,z);
if(y>mid) modify_max(rs,mid+1,r,x,y,z);
update(p);
}
void modify_min(int p,int l,int r,int x,int y,int z) {
if(z>=mx[p]) return ;
if(x<=l&&r<=y&&z>smx[p]) return push_max(p,l,r,z),void();
pushdown(p,l,r);
if(x<=mid) modify_min(ls,l,mid,x,y,z);
if(y>mid) modify_min(rs,mid+1,r,x,y,z);
update(p);
}
ll query_sum(int p,int l,int r,int x,int y) {
if(x<=l&&r<=y) return sum[p];
pushdown(p,l,r);ll ans=0;
if(x<=mid) ans+=query_sum(ls,l,mid,x,y);
if(y>mid) ans+=query_sum(rs,mid+1,r,x,y);
return ans;
}
int query_max(int p,int l,int r,int x,int y) {
if(x<=l&&r<=y) return mx[p];
pushdown(p,l,r);int ans=-inf;
if(x<=mid) ans=max(ans,query_max(ls,l,mid,x,y));
if(y>mid) ans=max(ans,query_max(rs,mid+1,r,x,y));
return ans;
}
int query_min(int p,int l,int r,int x,int y) {
if(x<=l&&r<=y) return mn[p];
pushdown(p,l,r);int ans=inf;
if(x<=mid) ans=min(ans,query_min(ls,l,mid,x,y));
if(y>mid) ans=min(ans,query_min(rs,mid+1,r,x,y));
return ans;
}
void build(int p,int l,int r) {
if(l==r) {
read(mx[p]),mn[p]=mx[p],sum[p]=mx[p];
smx[p]=-inf,smn[p]=inf;cntmx[p]=cntmn[p]=1;return ;
}build(ls,l,mid),build(rs,mid+1,r),update(p);
}
void debug(int p,int l,int r) {
if(l==r) {return ;}
pushdown(p,l,r),debug(ls,l,mid),debug(rs,mid+1,r),update(p);
}
}SGT;
signed main() {
read(n);SGT.build(1,1,n);
read(m);
for(int i=1;i<=m;i++) {
int op,x,y,z;
read(op),read(x),read(y);if(op<=3) read(z);
if(op==1) SGT.modify_add(1,1,n,x,y,z);
else if(op==2) SGT.modify_max(1,1,n,x,y,z);
else if(op==3) SGT.modify_min(1,1,n,x,y,z);
else if(op==4) write(SGT.query_sum(1,1,n,x,y));
else if(op==5) write(SGT.query_max(1,1,n,x,y));
else write(SGT.query_min(1,1,n,x,y));
}
return 0;
}