分块求调,50pts

P1253 扶苏的问题

Hedgehog_210508 @ 2022-07-06 22:18:57

4WA,1TLE

#include<bits/stdc++.h>
#define N 2000009
#define M 2009
#define inf 1e15+9
using namespace std;
typedef long long ll;
ll n,m,L,a[N],b[N],bm[M],c[M],v1[M],v2[N];
inline void add(ll l,ll r,ll x){
    if(b[l]==b[r])
        for(int i=l;i<=r;i++){
            if(v1[b[i]]>v2[i]) a[i]=x,v2[i]=v1[b[i]];
            else a[i]+=x;
            bm[b[i]]=max(bm[b[i]],a[i]+c[b[i]]);
        }
    else{
        for(int i=l;b[i]==b[l];i++){
            if(v1[b[i]]>v2[i]) a[i]=x,v2[i]=v1[b[i]];
            else a[i]+=x;
            bm[b[i]]=max(bm[b[i]],a[i]+c[b[i]]);
        }
        for(int i=r;b[i]==b[r];i--){
            if(v1[b[i]]>v2[i]) a[i]=x,v2[i]=v1[b[i]];
            else a[i]+=x;
            bm[b[i]]=max(bm[b[i]],a[i]+c[b[i]]);
        }
        for(int k=b[l]+1;k<=b[r]-1;k++) c[k]+=x,bm[k]+=x;
    }
    return;
}
inline void modi(ll l,ll r,ll x){
    if(b[l]==b[r])
        for(int i=l;i<=r;i++)
            v2[i]=v1[b[i]],a[i]=x;
    else{
        for(int i=l;b[i]==b[l];i++)
            v2[i]=v1[b[i]],a[i]=x;
        for(int i=r;b[i]==b[r];i--)
            v2[i]=v1[b[i]],a[i]=x;
        for(int k=b[l]+1;k<=b[r]-1;k++){
            v1[k]++;
            c[k]=x,bm[k]=x;
        }
    }
    return;
}
inline ll qw(ll l,ll r){
    ll ans=-inf;
    if(b[l]==b[r])
        for(ll i=l;i<=r;i++){
            if(v1[b[i]]>v2[i]) ans=max(ans,c[b[i]]);
            else ans=max(ans,a[i]+c[b[i]]);
        }
    else{
        for(ll i=l;b[i]==b[l];i++){
            if(v1[b[i]]>v2[i]) ans=max(ans,c[b[i]]);
            else ans=max(ans,a[i]+c[b[i]]);
        }
        for(ll i=r;b[i]==b[r];i--){
            if(v1[b[i]]>v2[i]) ans=max(ans,c[b[i]]);
            else ans=max(ans,a[i]+c[b[i]]);
        }
        for(ll k=b[l]+1;k<=b[r]-1;k++) ans=max(ans,bm[k]);
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(ll i=1;i<=n;i++) cin>>a[i];
    L=sqrt(n);
    for(ll i=1;i<=n;i++) b[i]=(i-1)/L+1;
    for(ll k=1;k<=b[n];k++){
        ll r=k*L;
        ll l=r-L+1;
        bm[k]=*max_element(a+l,a+r+1);
    }
    for(ll i=1;i<=m;i++){
        ll l,r,x,op;
        cin>>op>>l>>r;
        if(op==3) cout<<qw(l,r)<<endl;
        else{
            cin>>x;
            if(op==1) modi(l,r,x);
            else add(l,r,x);
        }
    }
    return 0;
}

by liangbowen @ 2022-07-06 22:23:57

TLE 说明又是一个要卡常的分块(

想练习分块,建议搞 ynoi,这题就线段树吧


by liangbowen @ 2022-07-06 22:30:00

分块理论复杂度 O(n\sqrt{n}),但本题 n = 10^6n\sqrt{n} = 10^9 加上一堆常数,原地爆炸

对于 TLE 的问题,尝试吸氧、手动调块长,要不然肯定会 T 掉


by Hedgehog_210508 @ 2022-07-06 22:31:30

wa又是什么原因呢


by Always_Remember_It @ 2023-10-02 19:19:27

@liangbowen 这题分块貌似不用卡常


|