hdu5306 Gorgeous Sequence

hdu5306 Gorgeous Sequence

题目大意

​ 给你一个序列,维护区间和,区间chkmin和区间最大值

数据范围

数据组数T,序列长度n,操作次数m

$T = 100,\sum n \leqslant 1000000 ,\sum m \leqslant 1000000 $

这是一道吉司机线段树的裸题,直接维护区间最大值,次大值,最大值个数,区间和就行了。

#include<bits/stdc++.h>
using namespace std;
#define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
#define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
typedef long long ll;
inline int read(){
	int x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c<'0' || c>'9'));
	if(c=='-') c=getchar(),f=-1;
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0');
	return x*f;
}
inline ll readll(){
	ll x;
	char c;
	ll f=1;
	while((c=getchar())!='-' && (c<'0' || c>'9'));
	if(c=='-') c=getchar(),f=-1;
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1ll)+(x<<3ll)+(c^'0');
	return x*f;
}
inline bool chkmax(int &x,int y){return (y>x)?(x=y,1):0;}
inline bool chkmin(int &x,int y){return (y<x)?(x=y,1):0;}
const int maxn=1e6+10;
struct Segment_tree{
	int Max[maxn<<2],Sec[maxn<<2],tot[maxn<<2],tag[maxn<<2];
	ll sum[maxn<<2];
	void push_up(int x){
		sum[x]=sum[x<<1]+sum[x<<1|1];
		Max[x]=Max[x<<1],tot[x]=tot[x<<1],Sec[x]=max(Sec[x<<1],Sec[x<<1|1]);
		if(chkmax(Max[x],Max[x<<1|1])) tot[x]=tot[x<<1|1],chkmax(Sec[x],Max[x<<1]);
		else if(Max[x]==Max[x<<1|1]) tot[x]+=tot[x<<1|1];
		else chkmax(Sec[x],Max[x<<1|1]);
	}
	void change(int x,int v){
		if(Max[x]<=v) return;
		sum[x]-=1ll*(Max[x]-v)*tot[x];
		Max[x]=tag[x]=v;
	}
	void push_down(int x){
		if(tag[x]==-1) return;
		change(x<<1,tag[x]);
		change(x<<1|1,tag[x]);
		tag[x]=-1;
	}
	void build_tree(int x,int L,int R){
		tag[x]=-1;
		if(L==R){
			Max[x]=read();tot[x]=1;
			Sec[x]=0;sum[x]=Max[x];
			return;
		}
		int Mid=(L+R)>>1;
		build_tree(x<<1,L,Mid);
		build_tree(x<<1|1,Mid+1,R);
		push_up(x);
	}
	void update(int x,int L,int R,int ql,int qr,int v){
		if(Max[x]<=v) return;
		if(ql<=L && R<=qr && Sec[x]<v){
			change(x,v);
			return;
		}
		int Mid=(L+R)>>1;
		push_down(x);
		if(ql<=Mid) update(x<<1,L,Mid,ql,qr,v);
		if(qr>Mid) update(x<<1|1,Mid+1,R,ql,qr,v);
		push_up(x);
	}
	int query_Max(int x,int L,int R,int ql,int qr){
		if(ql<=L && R<=qr) return Max[x];
		push_down(x);
		int Mid=(L+R)>>1,res=0;
		if(ql<=Mid) res=query_Max(x<<1,L,Mid,ql,qr);
		if(qr>Mid) chkmax(res,query_Max(x<<1|1,Mid+1,R,ql,qr));
		push_up(x);
		return res;
	}
	ll query_sum(int x,int L,int R,int ql,int qr){
		if(ql<=L && R<=qr) return sum[x];
		push_down(x);
		int Mid=(L+R)>>1;
		ll res=0;
		if(ql<=Mid) res=query_sum(x<<1,L,Mid,ql,qr);
		if(qr>Mid) res+=query_sum(x<<1|1,Mid+1,R,ql,qr);
		push_up(x);
		return res;
	}
}Seg;
int main(){
#ifndef ONLINE_JUDGE
	freopen("segment.in","r",stdin);
	freopen("segment.out","w",stdout);
#endif
	int T=read();
	while(T--){
		int n=read(),m=read();
		Seg.build_tree(1,1,n);
		while(m--){
			int ty=read(),l=read(),r=read();
			if(ty==0){
				int x=read();
				Seg.update(1,1,n,l,r,x);
			}
			else if(ty==1) printf("%d\n",Seg.query_Max(1,1,n,l,r));
			else printf("%lld\n",Seg.query_sum(1,1,n,l,r));
		}
	}
	return 0;
}
posted @ 2018-03-05 23:24  zhou888  阅读(133)  评论(0编辑  收藏  举报