P14507 缺零分治 mexdnc 离线解法

· · 题解

此题题解区似乎少一个离线解法,那我发一篇

思路

设全局 mexnow,那么。

以上结论很简单,请自行分析。

预处理

nxt[0]=b[1]

先使 nxt[i]=min(nxt[i-1],b[i+1])

再使 nxt[i]-=nxt[i+1]

此时 nxt[i] 表示以 i-1 为结尾 分割数量 。 (图中 F 表示一开始的 nxt)

对于 m >now

if xq<=nxt[ed]//如果最大的分割数量够
  nxt[ed]-=xq
  now+=ed*xq
else
  now+=nxt[ed]*ed
  nxt[ed]=0
  ed--

ed 表示最大的分割的位置,xq=ceil((m-now)/ed)) 由于分割的结尾最多有 n 个,所以是 O(n+q \log q)

代码

#include<bits/stdc++.h>

using namespace std;

#define int long long

int n,m;

template<typename T>
inline void read(T &x) {
    x = 0;
    register char c = getchar();
    register short f = 1;
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    x *= f;
}

template <typename T, typename... Args>

inline void read(T &x, Args &...temps)
{
    read(x), read(temps...);
}

void write(int x) {
    static int sta[35];
    int top = 0;
    do {
        sta[top++] = x % 10;
        x /= 10;
    } while (x);
    while (top) putchar(sta[--top] + '0');

}

const int N=2e5+5;

struct nod{
    int a,b;
}q[N];
bool cmp(nod x,nod y){
    return x.a<y.a;
}
struct Q{
    int x,id;
}xl[N];
bool cmp1(Q x,Q y){
    return x.x<y.x;
}
int ans[N];
int nxt[N];
void solve()
{
    memset(nxt,0,sizeof nxt);
    memset(ans,0,sizeof ans);
    memset(xl,0,sizeof xl);
    memset(q,0,sizeof q);  
    read(n,m);
    int minn=0; 
    for(int i=1;i<=n;i++){
        read(q[i].a,q[i].b);
        if(q[i].a==0){
            minn=1;
        }
    }
    int maxx=0;
    int gs=0;
    int tot=0;
    sort(q+1,q+1+n,cmp);
    int fl=1;
    if(q[1].a!=0){
        for(int i=1;i<=m;i++){
            int x;
            read(x);
            if(x==0){
                cout<<1;
                puts("");
            }
            else{
                cout<<-1;
                puts("");
            }
        }
        return;
    }
    for(int i=2;i<=n;i++){
        if(q[i].a==q[i-1].a+1){
            fl=max(fl,q[i].a+1);
        }
        else{
            break;
        }
    }

    gs=q[1].b;
    maxx+=gs;
    nxt[1]=gs;
    int ed=1;
    for(int i=2;i<=n;i++){
        if(q[i].a!=q[i-1].a+1) break;
        gs=min(gs,q[i].b);
        nxt[i]=gs;
        if(nxt[i]) ed=i;
        maxx+=gs;
    }

    for(int i=1;i<=ed;i++){
        nxt[i]-=nxt[i+1];
    }

    for(int i=1;i<=m;i++){
        read(xl[i].x);
        xl[i].id=i;
    }
    int now=fl;

    sort(xl+1,xl+1+m,cmp1);

    int bb=1;
    nxt[ed]--;
    for(int i=1;i<=m;i++){

        if(xl[i].x>maxx){
            ans[xl[i].id]=-1;
            continue;
        }
        if(xl[i].x<minn){
            ans[xl[i].id]=-1;
            continue;
        }
        if(xl[i].x<fl){
            ans[xl[i].id]=2;
            continue;
        }
        if(xl[i].x==fl){
            ans[xl[i].id]=1;
            continue;
        }

        while(xl[i].x>now&&ed>=0){
            int xq=ceil(1.0*(xl[i].x-now)/(1.0*ed));

            if(xq<nxt[ed]){

                now+=xq*ed;
                bb+=xq; 
                nxt[ed]-=xq;        
            }
            else{
                now+=nxt[ed]*ed;
                bb+=nxt[ed];
                ed--;
            }
        }
        if(ed<0&&xl[i].x>now){
            ans[xl[i].id]=-1;
        }
        else ans[xl[i].id]=bb;
        //if((xl[i].x-fl)/ed)
    }
    for(int i=1;i<=m;i++){
        cout<<ans[i]<<'\n';
    }
}
signed main(){
    int T;
    read(T);
    while(T--){
        solve();
    }
    return 0;
}

码风一坨,请批判性鉴赏~