HDU5306 Gorgeous Sequence

本题要求:

1.区间对\(x\)取 min
2.区间和
3.区间 min

只是吉司机线段树板子题。

即我们维护\(max,smax,cnt\),最大值和次大值,最大值的个数。

在往下过程中,当且仅当\(max > p > smax\)时进行操作。

那么我们很容易的统计。

#include<iostream>
#include<cstdio>
#define ll long long 
#define N 1000006

struct P{
	int mx,mx2,cmx,tag;
	ll s;
}e[N << 2];

int num[N];

inline int read(){
	int ans = 0;
	char a = getchar();
	while(! (a <= '9' && a >= '0')) a = getchar();
	while(a <= '9' && a >= '0')
	ans = (ans << 3) + (ans << 1) + (a - '0'),a = getchar();
	return ans;
}

#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define mid ((l + r) >> 1)
#define root 1,1,n
#define mx(x) e[x].mx
#define mx2(x) e[x].mx2
#define cnt(x) e[x].cmx
#define t(x) e[x].tag
#define s(x) e[x].s 
#define INF (0x7fffffff)

inline void up(int u){
	if(mx(ls(u)) < mx(rs(u))){
		mx(u) = mx(rs(u));
		cnt(u) = cnt(rs(u));
		mx2(u) = std::max(mx(ls(u)),mx2(rs(u)));
	}else{
		if(mx(ls(u)) > mx(rs(u))){
			mx(u) = mx(ls(u));
			cnt(u) = cnt(ls(u));
			mx2(u) = std::max(mx(rs(u)),mx2(ls(u)));
		}else{
			mx(u) = mx(ls(u));
			cnt(u) = cnt(ls(u)) + cnt(rs(u));
			mx2(u) = std::max(mx2(rs(u)),mx2(ls(u)));
		}
	}
	s(u) = s(ls(u)) + s(rs(u));
}

inline void build (int u,int l,int r){
	t(u) = -1;
	if(l == r){
		mx(u) = num[l];
		mx2(u) = t(u) = - 1;
		cnt(u) = 1;
		s(u) = num[l];  
		return ;
	}
	build(ls(u),l,mid);
	build(rs(u),mid + 1,r); 
	up(u);
}

inline void del(int u,ll tg){
	if(mx(u) <= tg){
		return ;
	}
	s(u) += (1ll * tg - mx(u)) * cnt(u);
	mx(u) = t(u) = tg;
}

inline void down(int u){
	if(t(u) == -1)return ;
	del(ls(u),t(u)),del(rs(u),t(u));
	t(u) = -1;
}

inline void modi(int u,int l,int r,int tl,int tr,ll p){
	if(mx(u) <= p)return ;
	if(tl <= l && r <= tr && mx2(u) < p){
		del(u,p);
		return;
	}
	down(u);
	if(tl <= mid)modi(ls(u),l,mid,tl,tr,p);
	if(tr > mid)modi(rs(u),mid + 1,r,tl,tr,p);
	up(u);
}

inline ll q(int u,int l,int r,int tl,int tr){
	if(tl <= l && r <= tr)
	return s(u);
	down(u);
	ll ans = 0;
	if(tl <= mid)
	ans = ans + q(ls(u),l,mid,tl,tr);
	if(tr > mid)
	ans = ans + q(rs(u),mid + 1,r,tl,tr);
	return ans;
}

inline ll q2(int u,int l,int r,int tl,int tr){
	if(tl <= l && r <= tr)
	return mx(u);
	down(u);
	ll ans = 0;
	if(tl <= mid)
	ans = std::max(ans,q2(ls(u),l,mid,tl,tr));
	if(tr > mid)
	ans = std::max(ans,q2(rs(u),mid + 1,r,tl,tr));
	return ans;
}


inline void solve(){
	int n,m;
	n = read(),m = read();
	for(int i = 1;i <= n;++i)
	num[i] = read();
	build(root);
	while(m -- ){
		int op,l,r;
		op = read(),l = read(),r = read();
		if(op == 0){
			int z;
			z = read();
			modi(root,l,r,z);
		}else{
			if(op == 2)
			std::cout<<q(root,l,r)<<std::endl;
			else
			std::cout<<q2(root,l,r)<<std::endl;
		}
	}
}

int main(){
	ll t;
	scanf("%lld",&t);
	while(t -- ){
		solve();
	}
}
posted @ 2021-08-05 18:35  fhq_treap  阅读(51)  评论(0)    收藏  举报