Description
Input
Output
Sample
Input:
10 10
4 9 5 9 4 4 4 7 3 5
3 4 10
2 39 35 39
3 37 34
2 26 16 31
2 28 19 31
1 19 28
3 27 28
3 23 26
3 12 9
3 8 11
Output:
36
25
18
15
12
12
Data Constraint
Hint
Analysis
智术短浅,不会
然后眼看大佬们陆陆续续切掉了这道题。。。
好像只需要维护最大值,最大值的个数,次大值,答案,就好了,至于证明用势能分析。
涨姿势了
说说怎么做
设最大值为mx,次大值smx,最大值的个数t
单个位置更改,easy
区间对于x取min
若
x≥mx
x
≥
m
x
,不会做任何改变
若
smx<x<mx
s
m
x
<
x
<
m
x
,只需要打个tag
若
smx≤x
s
m
x
≤
x
,就继续往下修改
怎么看怎么会炸啊
事实上并非如此
设势能
ϕ
ϕ
等值于线段树上每一个子树的不同值的个数
一开始最坏情况下
ϕ=O(nlogn)
ϕ
=
O
(
n
log
n
)
单点修改
O(logn)
O
(
log
n
)
,势能最多
ϕ=ϕ′+O(logn)
ϕ
=
ϕ
′
+
O
(
log
n
)
查询
O(1)
O
(
1
)
,
ϕ=ϕ′
ϕ
=
ϕ
′
对于区间取min
若
x≥mx
x
≥
m
x
,
ϕ=ϕ′
ϕ
=
ϕ
′
若
smx<x<mx
s
m
x
<
x
<
m
x
,
ϕ=ϕ′
ϕ
=
ϕ
′
若
smx≤x
s
m
x
≤
x
,至少使该个数减少1,多造成一次查找,
ϕ=ϕ′−O(1)
ϕ
=
ϕ
′
−
O
(
1
)
,增加的查找次数只可能使得势能变为1,而势能最大仅为
O((n+m)logn)
O
(
(
n
+
m
)
log
n
)
多造成查找的次数也是那么多,因此,总复杂度是
O(nlogn)
O
(
n
log
n
)
的。
codes
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 1000100
#define ll long long
using namespace std;
int n,m,a[N],nw,son[N][2],mx[N],smx[N],cnt[N],root,opl,opv,opr;
ll sum[N];
char ch[20];
ll read(){
ll s=1,x=0;char c;for(;(c=getchar())<'0' || c>'9';)if(c=='-')s=-1;
for(;c>='0' && c<='9';c=getchar()) x=(x<<1)+(x<<3)+c-48;return x*s;
}
void write(ll x){
int j=0;for(;x>0;x/=10)ch[++j]=x%10+48;
if(!j)ch[j=1]='0';while(j)putchar(ch[j--]);
putchar('\n');
}
void update(int x){
int l=son[x][0],r=son[x][1];sum[x]=sum[l]+sum[r];
mx[x]=mx[l];cnt[x]=cnt[l];smx[x]=smx[l];
if(mx[r]>mx[x]){
if(smx[r]>mx[x])smx[x]=smx[r];else smx[x]=mx[x];
mx[x]=mx[r];cnt[x]=cnt[r];
}else if(mx[x]==mx[r]){
cnt[x]+=cnt[r];if(smx[r]>smx[x])smx[x]=smx[r];
}else if(mx[r]>smx[x])smx[x]=mx[r];
}
int build(int h,int t){
int tmp=++nw,m=h+t>>1;
if(h==t){
mx[tmp]=smx[tmp]=a[h];cnt[tmp]=1;sum[tmp]=(ll)a[h];return tmp;
}son[tmp][0]=build(h,m);son[tmp][1]=build(m+1,t);
update(tmp);return tmp;
}
void dec(int w,int h,int t){
if(h==t){
int k=max((int)sum[w]-opv,0);
sum[w]=(ll)k;mx[w]=smx[w]=k;return;
}int m=h+t>>1;
if(m>=opl)dec(son[w][0],h,m);else dec(son[w][1],m+1,t);
update(w);
}
void lower(int w,int h,int t){
if(opl<=h && opr>=t){
if(mx[w]<=opv)return;
if(smx[w]<opv){sum[w]-=(ll)(mx[w]-opv)*(ll)(t-h+1);mx[w]=opv;return;}
}
if(h==t){
mx[w]=smx[w]=opv;sum[w]=(ll)opv;return;
}int m=h+t>>1;
if(m>=opl)lower(son[w][0],h,m);if(m<opr)lower(son[w][1],m+1,t);
update(w);
}
ll query(int w,int h,int t){
if(opl<=h && opr>=t)return sum[w];int m=h+t>>1;ll r=0;
if(m>=opl)r+=query(son[w][0],h,m);if(m<opr)r+=query(son[w][1],m+1,t);return r;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)a[i]=read();root=build(1,n);
ll las=0;
for(int i=1;i<=m;i++){
ll s=read(),l=read(),r,x;l^=las;
if(s==1){
x=read();x^=las;opl=l;opv=x;dec(root,1,n);
}
if(s==2){
r=read();x=read();x^=las;r^=las;opl=l;opr=r;opv=x;lower(root,1,n);
}
if(s==3){
r=read();r^=las;opl=l;opr=r;write(las=query(root,1,n));
}
}
return 0;
}