【UOJ 169】【UR #11】元旦老人与数列

题链

此题与洛谷P6242 【模板】线段树 3为孪生题

#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
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 1e18
#define mod 998244353
#define Pi acos(-1.0)
#define Pair pair<LL,LL>

LL n,m,k;
LL minf[MS<<2];
LL minse[MS<<2];
LL laminf[MS<<2];
LL laoth[MS<<2];

LL hisminf[MS<<2];
LL lahisminf[MS<<2];
LL lahisoth[MS<<2];

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){
	minf[rt] = min(minf[ls],minf[rs]);
	hisminf[rt] = min(hisminf[ls],hisminf[rs]);
	if(minf[ls] == minf[rs])
		minse[rt] = min(minse[ls],minse[rs]);
	else if(minf[ls] < minf[rs])
		minse[rt] = min(minse[ls],minf[rs]);
	else 
		minse[rt] = min(minf[ls],minse[rs]);
	
}

void update(int rt,LL k1,LL k2,LL k3,LL k4){
	hisminf[rt] = min(hisminf[rt],minf[rt]+k3);
	lahisminf[rt] = min(lahisminf[rt],laminf[rt]+k3);
	lahisoth[rt] = min(lahisoth[rt],laoth[rt]+k4);
	
	minf[rt] += k1;
	if(minse[rt] != INF) minse[rt] += k2;
	laminf[rt] += k1;
	laoth[rt] += k2;
}

void push_down(int rt){
	LL minn = min(minf[ls],minf[rs]);
	if(minf[ls] == minn) update(ls,laminf[rt],laoth[rt],lahisminf[rt],lahisoth[rt]);
	else update(ls,laoth[rt],laoth[rt],lahisoth[rt],lahisoth[rt]);
	if(minf[rs] == minn) update(rs,laminf[rt],laoth[rt],lahisminf[rt],lahisoth[rt]);
	else update(rs,laoth[rt],laoth[rt],lahisoth[rt],lahisoth[rt]);
	
	laminf[rt] = laoth[rt] = 0;
	lahisminf[rt] = lahisoth[rt] = 0;
}

void build(int l,int r,int rt){
	laminf[rt] = 0;
	laoth[rt] = 0;
	lahisminf[rt] = 0;
	lahisoth[rt] = 0;
	if(l == r){
		LL x;
		x = read();
		minf[rt] = x;
		minse[rt] = INF;
		hisminf[rt] = x;
		return;
	}
	int m = l+r>>1;
	build(l,m,ls);
	build(m+1,r,rs);
	push_up(rt);
}

void update_add(int L,int R,int l,int r,int rt,LL val){
	if(L <= l && r <= R){
		update(rt,val,val,val,val);
		return;
	}
	push_down(rt);
	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_max(int L,int R,int l,int r,int rt,LL val){
	if(minf[rt] >= val) return;
	if(L <= l && r <= R && minse[rt] > val){
		update(rt,val-minf[rt],0,val-minf[rt],0);
		return;
	}
	push_down(rt);
	int m = l+r>>1;
	if(m >= L) update_max(L,R,l,m,ls,val);
	if(m <  R) update_max(L,R,m+1,r,rs,val);
	push_up(rt);
}

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

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

int main() {
	//ios::sync_with_stdio(false);
	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_max(l,r,1,n,1,val);
		}
		else if(op == 3){
			printf("%lld\n",get_min(l,r,1,n,1));
		}
		else{
			printf("%lld\n",get_hismin(l,r,1,n,1));
		} 
	}
	

	return 0;
}
posted @ 2021-03-02 22:01  棉被sunlie  阅读(109)  评论(0)    收藏  举报