题解:P14311 【MX-S8-T4】平衡三元组
KingGojianOfYue · · 题解
怎么没人打块啊。
赛时由于以为 lower_bound 是小于等于,调了
我们将
要求
我们将原序列分成
区间加就直接整块打标记,散块暴力改。
对于查询,散块直接暴力前缀后缀查,整块需要搞出来的比较多左右端点在块内或块外的答案。但似乎左端点在块内右端点在块外或相反的情况不太好搞。我们以左端点在块内右端点在块外为例。由
细节可能比较多,慢慢调就好了。时间复杂度为
然后就是喜闻乐见的卡常环节:
-
注意一下你的块长。理论跟实际是不太一样的;
-
sort 很慢,换成基排(感谢 @lyms_Hz17 的建议);
-
选对语言。
最后也是喜提最优解倒数第一页。
代码是良心真短,不算快读只有 5KB。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3fll
using namespace std;
//此处省略快读
unsigned bucket[256];
#define SORTBYTE(TYPE, FR, TO, LEN, BIT) {\
memset(bucket, 0, sizeof(bucket));\
for (TYPE *it = (FR) + LEN; it != (FR); it--)\
++bucket[(it[-1] >> BIT) & 255];\
for (unsigned *it = bucket; it != bucket + 255; it++)\
it[1] += it[0];\
for (TYPE *it = (FR) + LEN; it != (FR); it--)\
(TO)[--bucket[(it[-1] >> BIT) & 255]] = it[-1];\
}
#define pll pair<long long,long long>
#define PSORTBYTE(TYPE, FR, TO, LEN, BIT) {\
memset(bucket, 0, sizeof(bucket));\
for (TYPE *it = (FR) + LEN; it != (FR); it--)\
++bucket[(it[-1].first >> BIT) & 255];\
for (unsigned *it = bucket; it != bucket + 255; it++)\
it[1] += it[0];\
for (TYPE *it = (FR) + LEN; it != (FR); it--)\
(TO)[--bucket[(it[-1].first >> BIT) & 255]] = it[-1];\
}
constexpr int N=1e6+5;
constexpr int B=4e3+5,block=1050;
long long a[N],b[N],pre2[N],suf2[N],pre[N],suf[N];
long long sum,st,k,ans[B];
pll c[N],d[N],c2[N],d2[N];
int n,q,bl[N],L[B],R[B],add[B];
inline void push_down(int x){
for(int i=L[x];i<=R[x];++i)b[i]=(a[i]+=add[x])+2000000000;add[x]=0;
SORTBYTE(long long,b+L[x],pre2+L[x],R[x]-L[x]+1,0);
SORTBYTE(long long,pre2+L[x],b+L[x],R[x]-L[x]+1,8);
SORTBYTE(long long,b+L[x],pre2+L[x],R[x]-L[x]+1,16);
SORTBYTE(long long,pre2+L[x],b+L[x],R[x]-L[x]+1,24);
for(int i=L[x];i<=R[x];++i)b[i]-=2000000000;
pre[L[x]]=a[L[x]];for(int i=L[x]+1;i<=R[x];++i)pre[i]=max(pre[i-1],a[i]);
suf[R[x]]=a[R[x]];for(int i=R[x]-1;i>=L[x];--i)suf[i]=max(suf[i+1],a[i]);
ans[x]=-inf;
for(int i=L[x]+1;i<R[x];++i)
if((a[i]<<1)<=pre[i-1]+suf[i+1])ans[x]=max(ans[x],a[i]+pre[i-1]+suf[i+1]);
for(int i=L[x];i<R[x];++i)
c2[i]=make_pair((a[i+1]<<1)-pre[i]+6000000000ll,a[i+1]+pre[i]),d2[i]=make_pair((a[i]<<1)-suf[i+1]+6000000000ll,a[i]+suf[i+1]);
PSORTBYTE(pll,c2+L[x],c+L[x],R[x]-L[x],0);
PSORTBYTE(pll,c+L[x],c2+L[x],R[x]-L[x],8);
PSORTBYTE(pll,c2+L[x],c+L[x],R[x]-L[x],16);
PSORTBYTE(pll,c+L[x],c2+L[x],R[x]-L[x],24);
PSORTBYTE(pll,c2+L[x],c+L[x],R[x]-L[x],32);
PSORTBYTE(pll,d2+L[x],d+L[x],R[x]-L[x],0);
PSORTBYTE(pll,d+L[x],d2+L[x],R[x]-L[x],8);
PSORTBYTE(pll,d2+L[x],d+L[x],R[x]-L[x],16);
PSORTBYTE(pll,d+L[x],d2+L[x],R[x]-L[x],24);
PSORTBYTE(pll,d2+L[x],d+L[x],R[x]-L[x],32);
c[L[x]].first-=6000000000ll,d[L[x]].first-=6000000000ll;
for(int i=L[x]+1;i<R[x];++i)c[i].first-=6000000000ll,d[i].first-=6000000000ll,
c[i].second=max(c[i].second,c[i-1].second),d[i].second=max(d[i].second,d[i-1].second);
}
inline void query(int l,int r){
sum=-inf;
if(bl[l]==bl[r]){
pre2[l]=a[l]+add[bl[l]];
suf2[r]=a[r]+add[bl[l]];for(int i=r-1;i>l;--i)suf2[i]=max(suf2[i+1],a[i]+add[bl[l]]);
for(int i=l+1;i<r;++i){
pre2[i]=max(pre2[i-1],a[i]+add[bl[l]]);
if(((a[i]+add[bl[l]])<<1)<=pre2[i-1]+suf2[i+1])
sum=max(sum,a[i]+add[bl[l]]+pre2[i-1]+suf2[i+1]);
}
(sum==-inf)?(cout<<"No\n"):(cout<<sum<<'\n');
return;
}
pre2[l]=a[l]+add[bl[l]];for(int i=l+1;i<=R[bl[l]];++i)pre2[i]=max(pre2[i-1],a[i]+add[bl[l]]);
suf2[r]=a[r]+add[bl[r]];for(int i=r-1;i>=L[bl[r]];--i)suf2[i]=max(suf2[i+1],a[i]+add[bl[r]]);
for(int i=bl[l]+1;i<bl[r];++i)pre2[R[i]]=max(pre[R[i]]+add[i],pre2[R[i-1]]);
for(int i=bl[r]-1;i>bl[l];--i)suf2[L[i]]=max(suf[L[i]]+add[i],suf2[L[i+1]]);
for(int i=R[bl[l]];i>=l;--i)suf2[i]=max(suf2[i+1],a[i]+add[bl[l]]);
for(int i=L[bl[r]];i<=r;++i)pre2[i]=max(pre2[i-1],a[i]+add[bl[r]]);
for(int i=R[bl[l]];i>l;--i)if(a[i]+add[bl[l]]+a[i]+add[bl[l]]<=pre2[i-1]+suf2[i+1])
sum=max(sum,a[i]+add[bl[l]]+pre2[i-1]+suf2[i+1]);
for(int i=L[bl[r]];i<r;++i)if(a[i]+add[bl[r]]+a[i]+add[bl[r]]<=pre2[i-1]+suf2[i+1])
sum=max(sum,a[i]+add[bl[r]]+pre2[i-1]+suf2[i+1]);
for(int i=bl[l]+1;i<bl[r];++i){
if(ans[i]!=-inf)sum=max(sum,ans[i]+add[i]+add[i]+add[i]);
st=pre2[R[i-1]]+suf2[L[i+1]];
if(b[L[i]]<=((st)>>1)-add[i]){
sum=max(sum,(*(upper_bound(b+L[i],b+R[i]+1,((st)>>1)-add[i])-1))+add[i]+st);
}
if(c[L[i]].first<=suf2[L[i+1]]-add[i]){
sum=max(sum,(*(upper_bound(c+L[i],c+R[i],make_pair(suf2[L[i+1]]-add[i],inf))-1)).second+add[i]+add[i]+suf2[L[i+1]]);
}
if(d[L[i]].first<=pre2[R[i-1]]-add[i]){
sum=max(sum,(*(upper_bound(d+L[i],d+R[i],make_pair(pre2[R[i-1]]-add[i],inf))-1)).second+add[i]+add[i]+pre2[R[i-1]]);
}
}
(sum==-inf)?(cout<<"No\n"):(cout<<sum<<'\n');
return;
}
inline void update(int l,int r,long long x){
if(bl[l]==bl[r]){
for(int i=l;i<=r;++i)a[i]+=x;
push_down(bl[l]);
return;
}
for(int i=R[bl[l]];i>=l;--i)a[i]+=x;
for(int i=L[bl[r]];i<=r;++i)a[i]+=x;
push_down(bl[l]);push_down(bl[r]);
for(int i=bl[l]+1;i<bl[r];++i)add[i]+=x;
}
signed main(){
cin>>n>>q;
for(int i=1;i<=n;++i)cin>>a[i];
for(int i=1;i<=block;++i)bl[i]=1;
for(int i=block+1;i<=n;++i)bl[i]=bl[i-block]+1;
for(int i=1;i<=bl[n];++i)L[i]=(i-1)*block+1,R[i]=min(i*block,n),push_down(i);
int op,l,r;long long x;
for(int i=1;i<=q;++i)cin>>op>>l>>r,(op==1)?(query(l,r)):(cin>>x,update(l,r,x));
return 0;
}