线段树求调 10pts
查看原帖
线段树求调 10pts
372238
lct201714楼主2024/10/25 16:27

重载了Num 类型的运算

max 包含 最大值,次大值,最大值个数

min 包含 最小值,次小值,最小值个数

代码如下 :

#include<bits/stdc++.h>
#define ll long long
#define MX LLONG_MAX
#define MN LLONG_MIN
using namespace std;
const int N=5e5+5;
template <class T>
inline void read(T &res){
	char c;bool f=0;
	while(!isdigit(c=getchar())) if(c=='-') f=1;
	res=(c^48);
	while(isdigit(c=getchar())) res=(res<<1)+(res<<3)+(c^48);
	if(f) res=~res+1;
}
int n,m,a[N];
#define ls (u<<1)
#define rs (u<<1|1)
#define mid (l+r>>1)
struct Num{
	ll num,se,count; 
	Num operator + (const ll& x) const {return (Num){num+x,se+x,count}; }  
	friend Num max(Num x,Num y){ 
		ll a,b,c;
		if(x.num==y.num){
			a=x.num;
			if(x.se>y.se) b=x.se;
			else b=y.se;
			c=x.count+y.count;
		}
		else if(x.num>y.num){
			a=x.num;
			if(x.se>y.num) b=x.se;
			else b=y.num;
			c=x.count;
		}
		else{
			a=y.num;
			if(x.num>y.se) b=x.num;
			else b=y.se;
			c=y.count;
		}
		return (Num){a,b,c};
	}
	friend Num min(Num x,Num y){
		ll a,b,c;
		if(x.num==y.num){
			a=x.num;
			if(x.se<y.se) b=x.se;
			else b=y.se;
			c=x.count+y.count;
		}
		else if(x.num<y.num){
			a=x.num;
			if(x.se<y.num) b=x.se;
			else b=y.num;
			c=x.count;
		}
		else{
			a=y.num;
			if(x.num<y.se) b=x.num;
			else b=y.se;
			c=y.count;
		}
		return (Num){a,b,c};
	}
};
struct SegTree{
	struct Tree{
		Num max,min;
		ll sum,tag,tag_min,tag_max;
	}t[N<<2];
	void push_up(int u,int l,int r){
		t[u].sum=t[ls].sum+t[rs].sum;
		t[u].max=max(t[ls].max,t[rs].max);
		t[u].min=min(t[ls].min,t[rs].min);
	}
	void build(int u,int l,int r){
		t[u].tag_min=MX; t[u].tag_max=MN;
		if(l==r){ 
			t[u].sum=a[l]; t[u].max=(Num){a[l],MN,1}; t[u].min=(Num){a[l],MX,1}; 
			return ;
		}
		build(ls,l,mid), build(rs,mid+1,r);
		push_up(u,l,r);
	}
	void Print(int u,int l,int r){
		printf("rt:%d -> [%d,%d] -- Sum:%lld ---Max <- ",u,l,r,t[u].sum);
		printf("(Num){%lld,%lld,%lld}\n",t[u].max.num,t[u].max.se,t[u].max.count);
		if(l==r) return ;
		Print(ls,l,mid), Print(rs,mid+1,r);
	}
	void add(int u,int l,int r,ll x){ t[u].sum+=(r-l+1)*x; t[u].max=t[u].max+x; t[u].min=t[u].min+x; t[u].tag+=x;} 
	void Min(int u,int l,int r,int x){
		if(t[u].max.num<=x) return ;
		else if(t[u].max.se<x){
			t[u].tag_min=x;
			t[u].sum-=(t[u].max.num-x)*t[u].max.count;
			t[u].max.num=x;
		}
		else{
			Min(ls,l,mid,x), Min(rs,mid+1,r,x);
			push_up(u,l,r);
		}
	}
	void Max(int u,int l,int r,int x){
		if(t[u].min.num>=x) return ;
		else if(t[u].min.se>x){
			t[u].tag_max=x;
			t[u].sum+=(x-t[u].min.num)*t[u].min.count;
			t[u].min.num=x;
		}
		else{
			Max(ls,l,mid,x), Max(rs,mid+1,r,x);
			push_up(u,l,r);
		}
	}
	void push_down(int u,int l,int r){
		if(t[u].tag){
			add(ls,l,mid,t[u].tag), add(rs,mid+1,r,t[u].tag);
			t[u].tag=0;
		}
		if(t[u].tag_min!=MX){ 
			Min(ls,l,mid,t[u].tag_min), Min(rs,mid+1,r,t[u].tag_min);
			t[u].tag_min=MX;
		}
		if(t[u].tag_max!=MN){
			Max(ls,l,mid,t[u].tag_max), Max(rs,mid+1,r,t[u].tag_max);
			t[u].tag_max=MN;
		}
	}
	void modify(int u,int l,int r,int ql,int qr,int x){ 
		if(l>qr||r<ql) return ;
		if(ql<=l&&r<=qr) return add(u,l,r,x);
		push_down(u,l,r);
		modify(ls,l,mid,ql,qr,x), modify(rs,mid+1,r,ql,qr,x);
		push_up(u,l,r);
	}
	void modify_min(int u,int l,int r,int ql,int qr,int x){
		if(l>qr||r<ql) return ;
		if(ql<=l&&r<=qr) return Min(u,l,r,x);
		push_down(u,l,r);
		modify_min(ls,l,mid,ql,qr,x), modify_min(rs,mid+1,r,ql,qr,x);
		push_up(u,l,r); 
	}
	void modify_max(int u,int l,int r,int ql,int qr,int x){
		if(l>qr||r<ql) return ;
		if(ql<=l&&r<=qr) return Max(u,l,r,x);
		push_down(u,l,r);
		modify_max(ls,l,mid,ql,qr,x), modify_max(rs,mid+1,r,ql,qr,x);
		push_up(u,l,r);
	}
	ll query_sum(int u,int l,int r,int ql,int qr){
		if(l>qr||r<ql) return 0;
		if(ql<=l&&r<=qr) return t[u].sum;
		push_down(u,l,r);
		return query_sum(ls,l,mid,ql,qr)+query_sum(rs,mid+1,r,ql,qr);
	}
	ll query_max(int u,int l,int r,int ql,int qr){ 
		if(l>qr||r<ql) return MN;
		if(ql<=l&&r<=qr) return t[u].max.num;
		push_down(u,l,r);
		return max(query_max(ls,l,mid,ql,qr),query_max(rs,mid+1,r,ql,qr));
	}
	ll query_min(int u,int l,int r,int ql,int qr){
		if(l>qr||r<ql) return MX;
		if(ql<=l&&r<=qr) return t[u].min.num;
		push_down(u,l,r);
		return min(query_min(ls,l,mid,ql,qr),query_min(rs,mid+1,r,ql,qr));
	}
}seg;
int main(){
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	read(m);  seg.build(1,1,n);
	for(int i=1,op,l,r,x;i<=m;i++){
		read(op); read(l),read(r);
		if(op==1){
			read(x); seg.modify(1,1,n,l,r,x);
		}
		if(op==2){
			read(x); seg.modify_max(1,1,n,l,r,x);
		}
		if(op==3){
			read(x); seg.modify_min(1,1,n,l,r,x);
		}
		if(op==4){
			cout<<seg.query_sum(1,1,n,l,r)<<"\n";
		}
		if(op==5){
			cout<<seg.query_max(1,1,n,l,r)<<"\n";
		}
		if(op==6){
			cout<<seg.query_min(1,1,n,l,r)<<"\n";
		}
//		seg.Print(1,1,n); cout<<"\n\n";
	}
	return 0;
} 
2024/10/25 16:27
加载中...