• bzoj2093: [Poi2010]Frog(单调队列,倍增)


    2093: [Poi2010]Frog

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 568  Solved: 186
    [Submit][Status][Discuss]

    Description

    一个条河无限宽,上面有n块石头,石头离左边的河岸(无限宽,右边河岸不晓得在哪)距离严格递增,现在Zxl想锻炼自己的跳跃能力(谁叫他在班里外号是鸟怪。。畸形),他在某一块石头上,想跳到离他这块石头第k远的石头上去,假如离他第k远的石头不是唯一的,他就选离岸最近的那一个(不然回不去了),他想你让他知道,从每块石头开始跳了m次后,自己在哪。

     

    Input

    第一行有3个由空格隔开的整数n, k (n, k <= 1,000,000), m (m <= 10^18)。
    第二行有n个正整数,第i个数表示第i块石头离左岸的距离,保证输入的n个正整数严格递增,并且不超过10^18。

     

    Output

    一行n个由空格隔开的整数,第i个表示Zxl从第i块石头开始跳,跳m次后会在哪个石头上。

     

    Sample Input

    5 2 4
    1 2 4 7 10

    Sample Output

    1 1 3 1 1
     
    /*
    如何求处离当前点第k近的点呢?
    答案是单调队列。因为离远点距离单调不减 所以可以维护一个长度为k+1的单调队列
    然后就是跳的问题。模型貌似是置换的快速幂,不会
    只会用倍增。空间开不下?滚动数组。 
    如果滚动数组倍增代码用for循环难理解,可以参考下面的一维版代码。 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    
    #define N 1000007
    #define ll long long 
    
    using namespace std;
    ll n,m,k,ans,cnt,a[N],p[N];
    int f[N][2],g[N];
    
    inline ll read()
    {
        ll x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int main()
    {
        n=read();k=read();m=read();
        for(int i=1;i<=n;i++) a[i]=read();
        ll l=1,r=k+1,lim=log2(m)+1;
        for(int i=1;i<=n;i++)
        {
            while(r<n && a[r+1]-a[i]<a[i]-a[l]) l++,r++;
            f[i][0]=(a[r]-a[i]>a[i]-a[l]?r:l);
        }
        
        if(m&1) for(int i=1;i<=n;i++) g[i]=f[i][0];
        else for(int i=1;i<=n;i++) g[i]=i;
        r=1;p[0]=1;
        for(int i=1;i<=lim;i++) p[i]=p[i-1]<<1;
        
        for(int j=1;j<=lim;j++)
        {
            for(int i=1;i<=n;i++) f[i][r]=f[f[i][r^1]][r^1];
            if(m&p[j]) for(int i=1;i<=n;i++) g[i]=f[g[i]][r];
            r^=1;
        }
        for(int i=1;i<=n;i++) printf("%d ",g[i]);printf("
    ");
        return 0;
    }
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    
    #define ll long long
    #define N 1000005
    
    using namespace std;
    int l,r;
    ll n,k,m,a[N];
    int f[N],tmp[N],g[N];
    
    inline ll read()
    {
        ll x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int main()
    {
        n=read();k=read();m=read();
        for(int i=1;i<=n;i++) a[i]=read();
        l=1;r=k+1;
        f[1]=a[1]-a[l]>=a[r]-a[1]?l:r;
        for(int i=2;i<=n;i++)
        {
            while(r<n&&a[i]-a[l]>a[r+1]-a[i]) l++,r++;
            f[i]=a[i]-a[l]>=a[r]-a[i]?l:r;
        }
        for(int i=1;i<=n;i++) g[i]=i;
        
        while(m)
        {
            if (m&1)
            {
                for(int i=1;i<=n;i++) tmp[i]=f[g[i]];
                for(int i=1;i<=n;i++) g[i]=tmp[i];
            }
            for(int i=1;i<=n;i++) tmp[i]=f[f[i]];
            for(int i=1;i<=n;i++) f[i]=tmp[i];
            m>>=1;
        }
        for(int i=1;i<=n-1;i++) printf("%d ",g[i]);
        printf("%d
    ",g[n]);
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    Devrama Slider
    全栈开发必备的10款 Sublime Text 插件
    经典网页设计:使用颜色滤镜效果的20个网站
    Nibbler – 免费的网站测试和指标评分工具
    使用 HTML5 Canvas 绘制出惊艳的水滴效果
    Qt4 和 Qt5 模块的分类
    设计Qt风格的C++API
    Qt属性系统
    Qt实现艺术字效果
    Qt中容器类应该如何存储对象(最好使用对象指针类型,如:QList<TestObj*>,而不要使用 QList<TestObj> 这样的定义,建议采用 智能指针QSharedPointer)
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7787456.html
Copyright © 2020-2023  润新知