zoukankan      html  css  js  c++  java
  • CF1032G Chattering

    Solution

    能够显然的想到每个人传递必然是连续的,也就是对于一个 (i) ,他能够到达的区间为 ([i-a_i,i+a_i])

    下一次,就会转移到 ([l,r]) 中能往左和往右的最远端点,所以我们需要记录最值,那么不难想到用ST表去处理区间最值。

    (l_{i,j}) 表示从 (j) 开始 (2^i) 秒能达到的最左端, (r_{i,j}) 同理。然后转移就是 (l_{i,j}=minlimits_{l_{i-1,j}leq tleq r_{i-1,j}}{l_{i-1,t}}\r_{i,j}=maxlimits_{l_{i-1,j}leq tleq r_{i-1,j}}{r_{i-1,t}})

    最后倍增求解即可。

    大细节:因为是在一个环上,并且同时在两个方向走,所以要将环拆开,并复制成三份,然后再进行ST表等操作。

    小细节:当区间覆盖超过 (n) 时,是完全覆盖,肯定有比选此时更优的解,跳过此时即可。

    时间复杂度: (O(nlog n)) (好像比CF官方说的好一点?)

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N=3e5+10;
    int n,a[N],b[N],c[N];
    int Log[N];
    int l[19][N],r[19][N];
    
    struct rmq{
        int st[N][19],val[N];
        int type;
        inline int Max(int x,int y){
            return (val[x]<val[y])?y:x;
        }
        void build(int *b,int n,int _type){
            type=_type;
            for(int i=1;i<=n;i++) st[i][0]=i,val[i]=type*b[i];
            for(int j=1;j<=Log[n];j++){
                for(int i=1;i+(1<<j)-1<=n;i++)
                    st[i][j]=Max(st[i][j-1],st[i+(1<<j-1)][j-1]);
            }
        }
        inline int query(int l,int r){
            int k=Log[r-l+1];
            return Max(st[l][k],st[r-(1<<k)+1][k]);
        }
    }rmq_l,rmq_r;
    
    int main(){
        scanf("%d",&n);
        for(int i=2;i<=3*n;i++) Log[i]=Log[i>>1]+1;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            a[i+n]=a[i+n*2]=a[i];
        }
        if(n==1) return puts("0"),0;
        for(int i=1;i<=3*n;i++){
            b[i]=max(1,i-a[i]);
            c[i]=min(3*n,i+a[i]);
        }
        for(int i=0;i<=Log[3*n];i++) r[i][3*n]=3*n,l[i][1]=1;
        for(int i=1;i<=3*n;i++){
            l[0][i]=b[i];
            r[0][i]=c[i];
        }
        rmq_l.build(l[0],n*3,-1);rmq_r.build(r[0],n*3,1);
        for(int i=1;i<=Log[3*n];i++)
            for(int j=1;j<=3*n;j++){
                int posl=rmq_l.query(l[i-1][j],r[i-1][j]);  
                int posr=rmq_r.query(l[i-1][j],r[i-1][j]);
                l[i][j]=min(l[i-1][posl],l[i-1][posr]);
                r[i][j]=max(r[i-1][posl],r[i-1][posr]);
            }
        for(int j=n+1;j<=n*2;j++){
            int u=j,v=j;
            int ans=0;
            for(int i=Log[3*n];i>=0;i--){
                if(max(r[i][v],r[i][u])-min(l[i][u],l[i][v])+1>=n) continue;
                int nu=rmq_l.query(l[i][u],r[i][v]);
                int nv=rmq_r.query(l[i][u],r[i][v]);
                u=nu;v=nv; 
                ans+=1<<i;
            }
            ans++;
            printf("%d ",ans);
        }
        puts("");
        return 0;
    }
    
  • 相关阅读:
    WrapPanel虚拟化
    关于Windows执行cmd命令的坑之一
    C# .Net 获取当前电脑上的可移动磁盘
    关于WPF中资源字典的内存优化
    WPF获取ListBox、ListView之类列表的ScrollViewer实例
    C#事件与委托 yangan
    系统自动登录设置(适用所有操作系统) yangan
    Oracel小知识记录 yangan
    使用avaScript获取Url中的指定参数值 yangan
    Win7下破解ArcGIS 9.3方法 yangan
  • 原文地址:https://www.cnblogs.com/jasony/p/13817541.html
Copyright © 2011-2022 走看看