前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CodeForces #549 Div.2 ELynyrd Skynyrd

CodeForces #549 Div.2 ELynyrd Skynyrd

作者头像
ShenduCC
发布2019-05-09 16:04:01
2570
发布2019-05-09 16:04:01
举报
文章被收录于专栏:算法修养算法修养

题目

这道题目实际上可以用动态规划来做。

对于每个区间,我们从右边边界,往左边走,如果能走n-1次,那说明以右边边界为起点存在一个题目中说的子链。

利用倍增算法,实际上倍增也是动态规划。f[i][j] 表示以i为结尾,能够往前走 2^j 次所到达的位置。

最后就是寻找以每个点为右边边界,往前走,能走到n-1次的,并且走的距离最近的的那点,那么在这个点的左边都是满足条件的,在这个点的右边都是不满足条件的。

AC代码

代码语言:javascript
复制
#include <iostream>
#include <stdio.h>
#include <math.h>

using namespace std;

#define N 200000
int n,m,q;
int f[N+5][20];
int pre[N+5];
int p[N+5];
int a[N+5];
int last[N+5];
int res[N+5];


int find(int x,int i)
{
    if(x==0)
        return i;
    int j=0;
    while(1)
    {
        if((int)pow(2.0,j)>x)
            break;
        else
            j++;
    }
    if(f[i][j-1]!=0) {

        x -= (int) pow(2.0, j - 1);
        return find(x, f[i][j - 1]);
    } else
        return -1;
}

int main()
{
    scanf("%d%d%d",&n,&m,&q);

    for(int i=0;i<n;i++)
    {
        scanf("%d",&p[i]);
        if(i!=0)
            pre[p[i]]=p[i-1];
    }
    pre[p[0]]=p[n-1];
    memset(last,0,sizeof(last));
    memset(f,0,sizeof(f));
    memset(res,-1,sizeof(res));
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&a[i]);
        last[a[i]]=i;
        f[i][0] = last[pre[a[i]]];
        for(int j=1;j<20;j++)
        {
            f[i][j]=f[f[i][j-1]][j-1];
        }
    }

    for(int i=1;i<=m;i++)
    {
        int x=find(n-1,i);
        res[i]=max(res[i-1],x);
    }

    int l,r;
    for(int i=0;i<q;i++)
    {
        scanf("%d%d",&l,&r);
        if(l<=res[r])
            printf("1");
        else
            printf("0");
    }
    printf("\n");


    return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-04-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档