loading

P7447 [Ynoi2007] rgxsxrs

题意

给定一个长度为 \(n\) 的序列,有 \(q\) 次操作:区间将 \(>x\) 的数减掉 \(x\),区间查询和以及两个最值。

强制在线,\(n,q\le 5\times10^5,6\text{s},64\text{MB}\)

分析

倍增值域分块。

忘了哪篇文章说的了,倍增值域分块适用于数值单调的情形。

有一个做法就是线段树维护区间最大值,区间递归到叶子修改,如果区间最大值 \(\le x\) 就退出。用 10^9 1 10^9 1 10^9 1... q*1 1 n 1 卡到平方。

考虑倍增值域分块,底数为 \(B\),对每个块维护一棵线段树,假设 \(x\) 位于第 \(p\) 个块,那么对于 \([1,p-1]\) 这些块不需要任何处理,对于第 \(p\) 个块,执行上面说的那个被卡到平方的暴力,由于块内的一个数被同块的数减 \(b\) 次后必然变块,所以复杂度可以保证。对于 \([p+1,log_BV]\) 这些块,它们必然大于 \(x\),打一个区间减标记即可。然后考虑变块,直接线段树上暴力找即可,单次复杂度 \(O(\log n)\),一共变块 \(O(\log_B V)\) 次,总复杂度 \(O(n\log n(\log_BV+B))\),理论取 \(B=e\) 最优,实际我取的 \(B=32\) 才跑过去。

别急,此时空间复杂度 \(O(n\log_B V)\),不出意外的话这个空间肯定就爆了,考虑当区间长度到 \(L=O(\log n)\) 级别时,停止往下递归,改为在这段区间上面暴力操作,时间复杂度不变,空间复杂度变为 \(O(n)\),就能过了。

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#include<unordered_map>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<ctime>
#include<random>
#include<cassert>
#define x1 xx1
#define y1 yy1
#define IOS ios::sync_with_stdio(false)
#define ITIE cin.tie(0)
#define OTIE cout.tie(0)
#define PY puts("Yes")
#define PN puts("No")
#define PW puts("-1")
#define P0 puts("0")
#define P__ puts("")
#define PU puts("--------------------")
#define mp make_pair
#define fi first
#define se second
#define gc getchar
#define pc putchar
#define pb emplace_back
#define un using namespace
#define il inline
#define all(x) x.begin(),x.end()
#define mem(x,y) memset(x,y,sizeof x)
#define popc __builtin_popcountll 
#define rep(a,b,c) for(int a=(b);a<=(c);++a)
#define per(a,b,c) for(int a=(b);a>=(c);--a)
#define reprange(a,b,c,d) for(int a=(b);a<=(c);a+=(d))
#define perrange(a,b,c,d) for(int a=(b);a>=(c);a-=(d))
#define graph(i,j,k,l) for(int i=k[j];i;i=l[i].nxt)
#define lowbit(x) ((x)&-(x))
#define lson(x) ((x)<<1)
#define rson(x) ((x)<<1|1)
//#define double long double
//#define int long long
//#define int __int128
using namespace std;
using i64=long long;
using u64=unsigned long long;
using pii=pair<int,int>;
template<typename T1,typename T2>inline void ckmx(T1 &x,T2 y){x=x>y?x:y;}
template<typename T1,typename T2>inline void ckmn(T1 &x,T2 y){x=x<y?x:y;}
inline auto rd(){
	int qwqx=0,qwqf=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')qwqf=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){qwqx=(qwqx<<1)+(qwqx<<3)+ch-48;ch=getchar();}return qwqx*qwqf;
}
template<typename T>inline void write(T qwqx,char ch='\n'){
	if(qwqx<0){qwqx=-qwqx;putchar('-');}
	int qwqy=0;static char qwqz[40];
	while(qwqx||!qwqy){qwqz[qwqy++]=qwqx%10+48;qwqx/=10;}
	while(qwqy--){putchar(qwqz[qwqy]);}if(ch)putchar(ch);
}
bool Mbg;
const int mod=998244353;
template<typename T1,typename T2>inline void adder(T1 &x,T2 y){x+=y,x=x>=mod?x-mod:x;}
template<typename T1,typename T2>inline void suber(T1 &x,T2 y){x-=y,x=x<0?x+mod:x;}
const int maxn=5e5+5,inf=0x3f3f3f3f;
const int L=36,K=5;
const long long llinf=0x3f3f3f3f3f3f3f3f;
int n,Q;
int a[maxn],bel[maxn];
//T[i]存[2^i,2^{i+1})
struct node{
	i64 sum,mx,mn;
	int len,num;
	int ls,rs;
	il node(){sum=num=len=ls=rs=0,mx=-llinf,mn=llinf;}
}d[maxn<<1];
int tag[maxn<<1];
int cnt;
int rt[30];
#define mid ((l+r)>>1)
il void pu(int p){
	d[p].sum=d[d[p].ls].sum+d[d[p].rs].sum;
	d[p].num=d[d[p].ls].num+d[d[p].rs].num;
	d[p].mn=min(d[d[p].ls].mn,d[d[p].rs].mn);
	d[p].mx=max(d[d[p].ls].mx,d[d[p].rs].mx);
}
il void rebd(int o,int l,int r,int p){
	tag[p]=0;
	d[p].sum=d[p].num=0,d[p].mn=llinf,d[p].mx=-llinf;
	rep(i,l,r){
		if(bel[i]==o){
			d[p].sum+=a[i],d[p].num++,ckmn(d[p].mn,a[i]),ckmx(d[p].mx,a[i]);
		}
	}
}
il void pt(int p,int v){
	d[p].sum+=1ll*d[p].num*v,d[p].mn+=v,d[p].mx+=v,tag[p]+=v;
}
il void pd(int p){
	if(tag[p]){
		pt(d[p].ls,tag[p]),pt(d[p].rs,tag[p]);
		tag[p]=0;
	}
}
void bd(int o,int l,int r,int &p){
	p=++cnt,d[p].len=r-l+1;
	if(d[p].len<=L)return rebd(o,l,r,p);
	bd(o,l,mid,d[p].ls),bd(o,mid+1,r,d[p].rs);
	pu(p);
}
void add(int o,int x,int l,int r,int p){
	if(d[p].len<=L){
		if(tag[p]){
			rep(i,l,r)if(bel[i]==o)a[i]+=tag[p];
			tag[p]=0;
		}
		bel[x]=o;
		rebd(o,l,r,p);
		return;
	}
	pd(p);
	x<=mid?add(o,x,l,mid,d[p].ls):add(o,x,mid+1,r,d[p].rs);
	pu(p);
}
void sp_upd(int o,int ll,int rr,int v,int l,int r,int p){
	if(d[p].mx<=v||!d[p].num||r<ll||rr<l)return;
	if(d[p].len<=L){
		if(tag[p]){
			rep(i,l,r)if(bel[i]==o)a[i]+=tag[p];
			tag[p]=0;
		}
		rep(i,max(ll,l),min(rr,r))if(bel[i]==o&&a[i]>v)a[i]-=v;
		rep(i,l,r)if(bel[i]==o&&a[i]<(1<<(o*K))){
			const int nbel=log2(a[i])/K;
			add(nbel,i,1,n,rt[nbel]);
		}
		rebd(o,l,r,p);
		return;
	}
	pd(p);
	sp_upd(o,ll,rr,v,l,mid,d[p].ls),sp_upd(o,ll,rr,v,mid+1,r,d[p].rs);
	pu(p);
}
void fnd(int o,int l,int r,int p){
	if(d[p].mn>=(1<<(o*K))||!d[p].num)return;
	if(d[p].len<=L){
		if(tag[p]){
			rep(i,l,r)if(bel[i]==o)a[i]+=tag[p];
			tag[p]=0;
		}
		rep(i,l,r)if(bel[i]==o&&a[i]<(1<<(o*K))){
			const int nbel=log2(a[i])/K;
			add(nbel,i,1,n,rt[nbel]);
		}
		rebd(o,l,r,p);
		return;
	}
	pd(p);
	fnd(o,l,mid,d[p].ls),fnd(o,mid+1,r,d[p].rs);
	pu(p);
}
void upd(int o,int ll,int rr,int v,int l,int r,int p){
	if(!d[p].num||r<ll||rr<l)return;
	if(d[p].len<=L){
		if(tag[p]){
			rep(i,l,r)if(bel[i]==o)a[i]+=tag[p];
			tag[p]=0;
		}
		rep(i,max(ll,l),min(rr,r))if(bel[i]==o){
			a[i]+=v;
			if(a[i]<(1<<(o*K))){
				const int nbel=log2(a[i])/K;
				add(nbel,i,1,n,rt[nbel]);
			}
		}
		rebd(o,l,r,p);
		return;
	}
	if(ll<=l&&r<=rr)return pt(p,v),fnd(o,l,r,p);
	pd(p);
	upd(o,ll,rr,v,l,mid,d[p].ls),upd(o,ll,rr,v,mid+1,r,d[p].rs);
	pu(p);
}
using arr=array<i64,3>;
il void merge(arr &x,arr y){
	x[0]+=y[0],ckmn(x[1],y[1]),ckmx(x[2],y[2]);
}
arr qry(int o,int ll,int rr,int l,int r,int p){
	if(d[p].len<=L){
		if(tag[p]){
			rep(i,l,r)if(bel[i]==o)a[i]+=tag[p];
			tag[p]=0;
		}
		i64 sum=0,mn=llinf,mx=-llinf;
		rep(i,max(ll,l),min(rr,r))if(bel[i]==o)sum+=a[i],ckmn(mn,a[i]),ckmx(mx,a[i]);
		return {sum,mn,mx};
	}
	if(ll<=l&&r<=rr)return {d[p].sum,d[p].mn,d[p].mx};
	pd(p);
	arr res={0,llinf,-llinf};
	if(ll<=mid)merge(res,qry(o,ll,rr,l,mid,d[p].ls));
	if(rr>mid)merge(res,qry(o,ll,rr,mid+1,r,d[p].rs));
	return res;
}
#undef mid
inline void solve_the_problem(){
	n=rd(),Q=rd();
	rep(i,1,n)a[i]=rd(),bel[i]=log2(a[i])/K;
	rep(i,0,29/K)bd(i,1,n,rt[i]);
	int lstans=0;
	rep(_,1,Q){
		int op=rd(),l=rd()^lstans,r=rd()^lstans,x;
		if(op==1){
			x=rd()^lstans;
			const int st=log2(x)/K;
			sp_upd(st,l,r,x,1,n,rt[st]);
			rep(i,st+1,29/K)upd(i,l,r,-x,1,n,rt[i]);
		}else{
			arr ans={0,inf,-inf};
			rep(i,0,29/K)merge(ans,qry(i,l,r,1,n,rt[i]));
			write(ans[0],32),write(ans[1],32),write(ans[2]);
			lstans=ans[0]&1048575;
		}
	}
}
bool Med;
signed main(){
//	freopen(".in","r",stdin);freopen(".out","w",stdout);
	fprintf(stderr,"%.3lfMB\n",(&Mbg-&Med)/1048576.0);
	int _=1;
	while(_--)solve_the_problem();
}
/*
g++ p7447.cpp -o a -std=c++14 -O2 -Wall -Wextra -Wshadow

5 2
2 4 5 1 3
1 2 4 3
2 1 5

10 9
22 36 30 21 9 13 52 9 83 41
1 5 9 72
2 6 7
2 3 3
1 4 7 54
2 3 7
1 4 9 51
2 4 10
2 1 6
2 2 2
output:
65 13 52
30 30 30
125 9 52
105 1 41
131 9 36
36 36 36

6 6
70 98 43 82 38 61
1 2 5 85
1 2 4 42
1 4 5 3
2 2 5
2 3 4
2 1 4
output:
86 1 37
38 1 37
121 1 70

6 6
84 62 9 37 18 73
1 2 6 4
1 4 4 54
1 1 6 21
1 1 2 92
2 3 6
2 2 4
output:
79 5 48
54 5 37
*/
posted @ 2025-07-08 18:56  dcytrl  阅读(18)  评论(0)    收藏  举报