洛谷P6242 【模板】线段树 3

题链

此题即Picks loves segment tree增加询问历史最值

#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#pragma GCC optimize(2)
using namespace std;
#define LL long long
#define ll long long
#define ULL unsigned long long
#define ls rt<<1
#define rs rt<<1|1
#define MS 500009
#define INF 20000009
#define mod 1000000007
#define Pi acos(-1.0)
#define Pair pair<LL,LL>
#define M 11431471
#define B 231
#define MM 37101101
#define BB 312

LL n,m,k;
LL sum[MS<<2]; // 区间和 
LL maxf[MS<<2]; // 区间最大值 
LL cntf[MS<<2]; // 区间最大值个数 
LL maxse[MS<<2]; // 区间第二大值 
LL lamaxf[MS<<2]; // la_区间最大值需加的数 
LL laoth[MS<<2]; // la_区间非最大值需加的数 
LL hismaxf[MS<<2]; // 区间历史最大值 
LL lahismaxf[MS<<2]; // la_最大的区间历史最大值需加的数 
LL lahisoth[MS<<2]; // la_非最大的区间历史最大值需加的数 

ll read(){
    char c=getchar();ll s=0,f=1;
    for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())s=s*10+c-48;
    return s*f;
}

void push_up(int rt){
	sum[rt] = sum[ls] + sum[rs];
	maxf[rt] = max(maxf[ls],maxf[rs]);
	hismaxf[rt] = max(hismaxf[ls],hismaxf[rs]); //
	if(maxf[ls] == maxf[rs]){
		cntf[rt] = cntf[ls] + cntf[rs];
		maxse[rt] = max(maxse[ls],maxse[rs]); 
	} 
	else if(maxf[ls] > maxf[rs]){
		cntf[rt] = cntf[ls];
		maxse[rt] = max(maxse[ls],maxf[rs]);
	}
	else{
		cntf[rt] = cntf[rs];
		maxse[rt] = max(maxf[ls],maxse[rs]);
	}
}

void build(int l,int r,int rt){
	lamaxf[rt] = 0;
	laoth[rt] = 0;
	lahismaxf[rt] = 0; 
	lahisoth[rt] = 0;
	if(l == r){
		LL x;
		x = read();
		sum[rt] = x;
		maxf[rt] = x;
		cntf[rt] = 1;
		maxse[rt] = -1e18;
		hismaxf[rt] = x; //
		return;
	}
	int m = l+r>>1;
	build(l,m,ls);
	build(m+1,r,rs);
	push_up(rt);
}

void update(int rt,int l,int r,LL k1,LL k2,LL k3,LL k4){
	// 最大值加成 ,非最大值加成 ,最大值的历史最大加成 ,非最大值的历史最大加成 
	sum[rt] += cntf[rt]*k1+(r-l+1-cntf[rt])*k2;
	//***// 
	hismaxf[rt] = max(hismaxf[rt],maxf[rt]+k3); //  
	lahismaxf[rt] = max(lahismaxf[rt],lamaxf[rt]+k3); // 
	lahisoth[rt] = max(lahisoth[rt],laoth[rt]+k4); //
	//***// 
	maxf[rt] += k1;
	if(maxse[rt] != -1e18) maxse[rt] += k2;
	lamaxf[rt] += k1;
	laoth[rt] += k2;
}

void push_down(int rt,int l,int r){
	int m = l+r>>1;
	LL maxn = max(maxf[ls],maxf[rs]);
	if(maxf[ls] == maxn) update(ls,l,m,lamaxf[rt],laoth[rt],lahismaxf[rt],lahisoth[rt]);
	else update(ls,l,m,laoth[rt],laoth[rt],lahisoth[rt],lahisoth[rt]);
	if(maxf[rs] == maxn) update(rs,m+1,r,lamaxf[rt],laoth[rt],lahismaxf[rt],lahisoth[rt]);
	else update(rs,m+1,r,laoth[rt],laoth[rt],lahisoth[rt],lahisoth[rt]);
	lamaxf[rt] = laoth[rt] = 0;
	lahismaxf[rt] = lahisoth[rt] = 0; //
}

void update_add(int L,int R,int l,int r,int rt,LL val){
	if(L <= l && r <= R){
		update(rt,l,r,val,val,val,val);
		return;
	}
	push_down(rt,l,r);
	int m = l+r>>1;
	if(m >= L) update_add(L,R,l,m,ls,val);
	if(m <  R) update_add(L,R,m+1,r,rs,val);
	push_up(rt);
}

void update_min(int L,int R,int l,int r,int rt,LL val){
	if(maxf[rt] <= val) return;
	if(L <= l && r <= R && val > maxse[rt]){
		update(rt,l,r,val-maxf[rt],0,val-maxf[rt],0);
		return;
	}
	push_down(rt,l,r);
	int m = l+r>>1;
	if(m >= L) update_min(L,R,l,m,ls,val);
	if(m <  R) update_min(L,R,m+1,r,rs,val);
	push_up(rt);
}

LL get_sum(int L,int R,int l,int r,int rt){
	if(L <= l && r <= R){
		return sum[rt];
	}
	push_down(rt,l,r);
	LL ans = 0;
	int m = l+r>>1;
	if(m >= L) ans += get_sum(L,R,l,m,ls);
	if(m <  R) ans += get_sum(L,R,m+1,r,rs);
	return ans;
}

LL get_max(int L,int R,int l,int r,int rt){
	if(L <= l && r <= R) return maxf[rt];
	push_down(rt,l,r);
	LL ans = -1e18;
	int m = l+r>>1;
	if(m >= L) ans = max(ans,get_max(L,R,l,m,ls));
	if(m <  R) ans = max(ans,get_max(L,R,m+1,r,rs));
	return ans;
}

LL get_hismax(int L,int R,int l,int r,int rt){ //
	if(L <= l && r <= R) return hismaxf[rt]; 
	push_down(rt,l,r);
	LL ans = -1e18;
	int m = l+r>>1;
	if(m >= L) ans = max(ans,get_hismax(L,R,l,m,ls));
	if(m <  R) ans = max(ans,get_hismax(L,R,m+1,r,rs));
	return ans;
}

void solve(){
	n = read() ,m = read();
	build(1,n,1);
	while(m--){
		LL op,l,r,val;
		op = read();
		l = read() ,r = read();
		if(op == 1){
			val = read();
			update_add(l,r,1,n,1,val);
		}
		else if(op == 2){
			val = read();
			update_min(l,r,1,n,1,val);
		} 
		else if(op == 3) printf("%lld\n",get_sum(l,r,1,n,1));
		else if(op == 4) printf("%lld\n",get_max(l,r,1,n,1));
		else printf("%lld\n",get_hismax(l,r,1,n,1));
	}
}

int main() {
	//ios::sync_with_stdio(false);
	LL te;
	te = 1;
	while(te--){
		solve();
	} 
	
	
	return 0;
}
posted @ 2021-02-23 20:58  棉被sunlie  阅读(179)  评论(0)    收藏  举报