Loj #6279. 数列分块入门 3

link: https://loj.ac/problem/6279

分块基本操作之一。

分块套平衡树。

#include<bits/stdc++.h>
#define ll long long
#define maxn 100005
using namespace std;
const ll inf=1ll<<61ll;
ll a[maxn],tag[405];
multiset<ll> s[405];
multiset<ll> ::iterator it;
int n,opt,m,le,sz,w;
int ri,add,bl[maxn];

inline void update(){
	if(bl[le]==bl[ri]){
		for(;le<=ri;le++){
			s[bl[le]].erase(a[le]);
			a[le]+=(ll)w;
			s[bl[le]].insert(a[le]);
		}
	}
	else{
		for(;bl[le]==bl[le-1];le++){
			s[bl[le]].erase(a[le]);
			a[le]+=(ll)w;
			s[bl[le]].insert(a[le]);			
		}
		for(;bl[ri]==bl[ri+1];ri--){
			s[bl[ri]].erase(a[ri]);
			a[ri]+=(ll)w;
			s[bl[ri]].insert(a[ri]);			
		}
		for(int j=bl[le];j<=bl[ri];j++){
			tag[j]+=(ll)w;
		}
	}
}

inline ll query(){
	ll an=-inf;
	if(bl[le]==bl[ri]){
		for(;le<=ri;le++){
			if(a[le]+tag[bl[le]]<w) an=max(an,a[le]+tag[bl[le]]);
		}
	}
	else{
		for(;bl[le]==bl[le-1];le++){
			if(a[le]+tag[bl[le]]<w) an=max(an,a[le]+tag[bl[le]]);			
		}
		for(;bl[ri]==bl[ri+1];ri--){
			if(a[ri]+tag[bl[ri]]<w) an=max(an,a[ri]+tag[bl[ri]]);			
		}
		for(int j=bl[le];j<=bl[ri];j++){
			it=s[j].lower_bound(w-tag[j]);
			an=max(an,(*(--it))+tag[j]);
		}
	}
	
	if(an==-inf) return -1;
	else return an;
}

int main(){
	scanf("%d",&n),sz=sqrt(n);
	for(int i=1;i<=n;i++){
		scanf("%lld",a+i);
		bl[i]=(i-1)/sz+1;
		s[bl[i]].insert(a[i]);
		
		if(bl[i]!=bl[i-1]) s[bl[i]].insert(-inf*2ll);
	}
	
	for(int i=1;i<=n;i++){
		scanf("%d%d%d%d",&opt,&le,&ri,&w);
		if(opt) printf("%lld
",query());
		else update();
	}
	
	return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/8510410.html