一种卡空间方法
查看原帖
一种卡空间方法
510957
DeepSeaSpray楼主2024/11/22 16:28

首先输入的数组都可以优化掉,重点在于队列。

队列空间不可释放,考虑手写链表模拟队列,采用 vector 动态开空间,并引入空间回收机制(维护被删掉的节点集合 bin,需要的时候清空复用,若为空直接新开空间)。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define i128 __int128
int n;
namespace IO{
    const unsigned top=(1<<30)-1;
    int typ,m,to;
    unsigned x,y,z,b1,b2,b;
    int P,L,R;
    inline void Init(){
        scanf("%d%d",&n,&typ);
        if(typ) scanf("%u%u%u%u%u%d",&x,&y,&z,&b1,&b2,&m);
    }
    inline int Read(){
        if(typ){
            to++;
            if(to==1) b=b1;
            else if(to==2) b=b2;
            else b=(x*b2+y*b1+z)&top,b1=b2,b2=b;
            if(P<to) scanf("%d%d%d",&P,&L,&R);
            return b%(R-L+1)+L;
        }
        else{int x;scanf("%d",&x);return x;}
    }
    int tp;
    char st[105];
    inline void Write(i128 x){
        while(x) st[++tp]=x%10+'0',x/=10;
        for(int i=tp;i>=1;i--) putchar(st[i]);
        tp=0;
    }
}
using IO::Init;
using IO::Read;
using IO::Write;
int hd,tl,tot;
vector<ll> s,v;
vector<i128> f;
vector<int> l,r;
vector<int> bin;
ll sum;
inline int New(){
    if(bin.empty()){
        s.emplace_back(0);
        v.emplace_back(0);
        f.emplace_back(0);
        l.emplace_back(0);
        r.emplace_back(0);
        return s.size()-1;
    }
    else{
        int t=bin.back();
        bin.pop_back();
        s[t]=v[t]=f[t]=l[t]=r[t]=0;
        return t;
    }
}
signed main(){
    Init();
    hd=tl=New(),tot++;
    for(int i=1;i<=n;i++){
        sum+=Read();
        while(tot>1&&v[r[hd]]<=sum)
            tot--,bin.emplace_back(hd),hd=r[hd];
        int t=New();
        s[t]=sum;
        v[t]=2*sum-s[hd];
        f[t]=f[hd]+(i128)(sum-s[hd])*(sum-s[hd]);
        while(tot>0&&v[t]<=v[tl])
            tot--,bin.emplace_back(tl),tl=l[tl];
        r[tl]=t,l[r[tl]]=tl,tl=t,tot++;
    }
    Write(f[tl]);
    return 0;
}

提供卡空间前的代码作为对照:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define i128 __int128
const int maxn=4e7;
int n;
namespace IO{
    const unsigned top=(1<<30)-1;
    int typ,m,to;
    unsigned x,y,z,b1,b2,b;
    int P,L,R;
    inline void Init(){
        scanf("%d%d",&n,&typ);
        if(typ) scanf("%u%u%u%u%u%d",&x,&y,&z,&b1,&b2,&m);
    }
    inline int Read(){
        if(typ){
            to++;
            if(to==1) b=b1;
            else if(to==2) b=b2;
            else b=(x*b2+y*b1+z)&top,b1=b2,b2=b;
            if(P<to) scanf("%d%d%d",&P,&L,&R);
            return b%(R-L+1)+L;
        }
        else{int x;scanf("%d",&x);return x;}
    }
    int tp;
    char st[105];
    inline void Write(i128 x){
        while(x) st[++tp]=x%10+'0',x/=10;
        for(int i=tp;i>=1;i--) putchar(st[i]);
        tp=0;
    }
}
using IO::Init;
using IO::Read;
using IO::Write;
ll s[maxn+5];
int p[maxn+5];
i128 f[maxn+5];
int hd,tl,q[maxn+5];
signed main(){
    Init();
    hd=tl=1;
    for(int i=1;i<=n;i++){
        s[i]=s[i-1]+Read();
        while(hd<tl&&2*s[q[hd+1]]-s[p[q[hd+1]]]<=s[i]) hd++;
        p[i]=q[hd];
        f[i]=f[p[i]]+(i128)(s[i]-s[p[i]])*(s[i]-s[p[i]]);
        while(hd<=tl&&2*s[i]-s[p[i]]<=2*s[q[tl]]-s[p[q[tl]]]) tl--;
        q[++tl]=i;
    }
    Write(f[n]);
    return 0;
}
2024/11/22 16:28
加载中...