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
*/

浙公网安备 33010602011771号