• 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();}
    
  • 相关阅读:
    洛谷P1501 动态树(LCT)
    Beijing Institute of Technology 2019.6 Monthly Contest (For grade 2018)
    [BJOI2018]求和
    [JSOI2015]最小表示
    简单题
    [Ynoi2016]掉进兔子洞
    乘积
    飞扬的小鸟
    [CTSC2008]网络管理
    Sequence
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15270848.html
Copyright © 2020-2023  润新知