NOIP 模拟 $50; m 第负二题$

题解 (by;zjvarphi)

首先考虑对于每一行二分答案 (k),考虑如何验证。

如果一个半径为 (k) 的菱形是在以当前行上的某一点为中心,且覆盖的格子全为 (1) 的一个最大菱形,那么 (k+1) 就是答案。

假设当前菱形的对称中心在第 (i) 行第 (y) 列,那么就会有

  1. (j<i) 时,(yge l_j+j+k-i)(yle r_j-j-k+i),要求 (y) 有解,所以 (max_{j=i-k}^il_j+j+k-ile min_{j=i-k}^ir_j-j-k+i)
  2. (j>i) 时,(yge l_j-j-k+i)(yle r_j+j-k-i),要求 (y) 有解,所以 (max_{j=i-k}^il_j-j-k+ile min_{j=i-k}^ir_j+j-k-i)

所以只需要维护 (l_j-j,l_j-j,r_j+j,r_j-j),可以用 (rmq) 预处理,复杂度 (mathcal{O m (nlogn)}),会超时。

考虑如何优化,首先发现 (|f_i-f_{i-1}|le 1),所以在下一回只用枚举三个答案。

其次,发现每一行所需要的判断范围单调不减,所以可以魔改一个单调队列。

所以,要维护四个单调队列,复杂度 (mathcal{O m(n)})

Code
#include<bits/stdc++.h>
#define Re register
#define ri Re signed
#define pd(i) ++i
#define bq(i) --i
namespace IO{
    char buf[1<<21],*p1=buf,*p2=buf;
    #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
    struct nanfeng_stream{
        template<typename T>inline nanfeng_stream &operator>>(T &x) {
            Re bool f=false;x=0;Re char ch=gc();
            while(!isdigit(ch)) f|=ch=='-',ch=gc();
            while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
            return x=f?-x:x,*this;
        }
    }cin;
}
using IO::cin;
namespace nanfeng{
    #define FI FILE *IN
    #define FO FILE *OUT
    template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
    template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
    using ull=unsigned long long;
    using ll=long long;
    static const int N=5e6+7,MOD=998244353;
    int l[N],r[N],f[N],cnt,res,nm,n,L,X,Y;
    ull A,B;
    ll cm[N],ans;
    auto random=[]() { 
        ull T=A,S=B; 
        A=S; 
        T^=T<<23; 
        T^=T>>17; 
        T^=S^(S>>26); 
        B=T; 
        return T+S; 
    }; 
    auto mk=[]() { 
        for (ri i(1);i<=n;pd(i)) { 
            l[i]=random()%L+X; 
            r[i]=random()%L+Y; 
            if (l[i]>r[i]) std::swap(l[i],r[i]); 
        } 
    }; 
    struct Dquel1{
        int que[N],hd=1,tl=0;
        std::function<bool(void)> exst=[=]() {return hd<=tl;};
        std::function<int(int)> calc=[&](int x) {return l[que[x]]+que[x];};
        std::function<void(int)> pop=[&](int lm) {while(hd<=tl&&que[hd]<lm) ++hd;};
        std::function<void(int)> add=[&](int lm) {while(hd<=tl&&calc(tl)<=l[lm]+lm) --tl;que[++tl]=lm;};
    }quel1;
    struct Dquel2{
        int que[N],hd=1,tl=0;
        std::function<bool(void)> exst=[=]() {return hd<=tl;};
        std::function<int(int)> calc=[&](int x) {return l[que[x]]-que[x];};
        std::function<void(int)> pop=[&](int lm) {while(hd<=tl&&que[hd]<lm) ++hd;};
        std::function<void(int)> add=[&](int lm) {while(hd<=tl&&calc(tl)<=l[lm]-lm) --tl;que[++tl]=lm;};
    }quel2;
    struct Dquer1{
        int que[N],hd=1,tl=0;
        std::function<bool(void)> exst=[=]() {return hd<=tl;};
        std::function<int(int)> calc=[&](int x) {return r[que[x]]-que[x];};
        std::function<void(int)> pop=[&](int lm) {while(hd<=tl&&que[hd]<lm) ++hd;};
        std::function<void(int)> add=[&](int lm) {while(hd<=tl&&calc(tl)>=r[lm]-lm) --tl;que[++tl]=lm;};
    }quer1;
    struct Dquer2{
        int que[N],hd=1,tl=0;
        std::function<bool(void)> exst=[=]() {return hd<=tl;};
        std::function<int(int)> calc=[&](int x) {return r[que[x]]+que[x];};
        std::function<void(int)> pop=[&](int lm) {while(hd<=tl&&que[hd]<lm) ++hd;};
        std::function<void(int)> add=[&](int lm) {while(hd<=tl&&calc(tl)>=r[lm]+lm) --tl;que[++tl]=lm;};
    }quer2;
    
    inline int main() {
        // FI=freopen("nanfeng.in","r",stdin);
        // FO=freopen("nanfeng.out","w",stdout);
        cin >> n >> L >> X >> Y >> A >> B;
        if (n==1) {puts("1");return 0;}
        nm=n;
        mk();
        cm[0]=1;
        for (ri i(1);i<=n;pd(i)) cm[i]=cm[i-1]*3%MOD;
        f[1]=1;
        quel1.add(1),quer1.add(1);
        for (ri i(2);i<=n;pd(i)) {
            f[i]=f[i-1]+1;
            int tml1=0,tml2=0,tmr1=0,tmr2=0;
            if (i+f[i-1]-1<=n) tml1=l[i+f[i-1]-1]-(i+f[i-1]-1),tmr1=r[i+f[i-1]-1]+(i+f[i-1]-1);
            if (i+f[i]-1<=n) tml2=l[i+f[i]-1]-(i+f[i]-1),tmr2=r[i+f[i]-1]+(i+f[i]-1);
            for (ri j(f[i]);j>=f[i-1]-1;bq(j)) {
                if (i+j-1>n||i-j+1<1||i+j-1<i-j+1) continue;
                int k=j-f[i-1];
                auto check=[&]() {
                    bool jud;
                    if (k==1) {
                        int l2=cmax(tml1,tml2),r2=cmin(tmr1,tmr2);
                        if (quel2.exst()) {
                            l2=cmax(l2,quel2.calc(quel2.hd));
                            r2=cmin(r2,quer2.calc(quer2.hd));
                        }
                        if (quel1.exst()) {
                            l2=cmax(l2+(j-1)+i,quel1.calc(quel1.hd)+j-1-i);
                            r2=cmin(r2-(j-1)-i,quer1.calc(quer1.hd)-j+1+i);
                        }
                        jud=(l2<=r2);
                        if (jud) {
                            quel2.add(i+f[i-1]-1),quel2.add(i+f[i]-1),quel2.pop(i+1);
                            quer2.add(i+f[i-1]-1),quer2.add(i+f[i]-1),quer2.pop(i+1);
                            quel1.add(i),quer1.add(i);
                        }
                    } else if (!k) {
                        int l2=tml1,r2=tmr1;
                        quel1.pop(i-j+1),quer1.pop(i-j+1);
                        if (quel2.exst()) {
                            l2=cmax(l2,quel2.calc(quel2.hd));
                            r2=cmin(r2,quer2.calc(quer2.hd));
                        }
                        if (quel1.exst()) {
                            l2=cmax(l2+(j-1)+i,quel1.calc(quel1.hd)+j-1-i);
                            r2=cmin(r2-(j-1)-i,quer1.calc(quer1.hd)-j+1+i);
                        }
                        jud=(l2<=r2);
                        if (jud) {
                            quel2.add(i+f[i-1]-1),quel2.pop(i+1);
                            quer2.add(i+f[i-1]-1),quer2.pop(i+1);
                            quel1.add(i),quer1.add(i);
                        }
                    } else {
                        quel1.pop(i-j+1),quer1.pop(i-j+1);
                        int l2=quel2.calc(quel2.hd),r2=quer2.calc(quer2.hd);
                        if (quel1.exst()) {
                            l2=cmax(l2+(j-1)+i,quel1.calc(quel1.hd)+j-1-i);
                            r2=cmin(r2-(j-1)-i,quer1.calc(quer1.hd)-j+1+i);
                        }
                        jud=(l2<=r2);
                        quel2.pop(i+1),quer2.pop(i+1);
                        quel1.add(i),quer1.add(i);
                    } 
                    return jud;
                };
                if (check()) {f[i]=j;break;} 
            }
        }
        for (ri i(1);i<=n;pd(i)) ans=(ans+cm[i-1]*f[i]%MOD)%MOD;
        printf("%lld
",ans);
        return 0;
    }
}
int main() {return nanfeng::main();}
原文地址:https://www.cnblogs.com/nanfeng-blog/p/15270848.html