[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;
}
posted @ 2019-01-06 19:57  Hyscere  阅读(290)  评论(0编辑  收藏  举报