cf1143E 倍增好题!

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf1143E 倍增好题!相关的知识,希望对你有一定的参考价值。

一开始感觉用莫队可以搞一下,但是看了题解才发现这题其实是倍增套路题

把排列转换成nxt数组,然后倍增dp[i][j]表示第i个数后面有(1<<j)个数的最靠左的区间

然后从右往左扫一次即可

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
int dp[maxn][20],last[maxn],nxt[maxn],ans[maxn],a[maxn],b[maxn],n,m,t;
//dp[i][j]表示第i个数开始的后面(1<<j)个数的位置 
int main(){
    cin>>n>>m>>t;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)nxt[a[i-1]]=a[i];    
    nxt[a[n]]=a[1];
    for(int i=1;i<=m;i++)cin>>b[i];
    for(int i=1;i<=n;i++)last[i]=m+1;
    for(int i=0;i<=19;i++)dp[m+1][i]=m+1;
    ans[m+1]=m+1;
    for(int i=m;i>=1;i--){
        dp[i][0]=last[nxt[b[i]]];
        last[b[i]]=i;
        for(int j=1;j<=19;j++)dp[i][j]=dp[dp[i][j-1]][j-1];
        int cnt=n-1,pos=i;
        for(int j=19;j>=0;j--)
            if(cnt >= (1<<j))
                cnt-=(1<<j),pos=dp[pos][j];
        ans[i]=min(ans[i+1],pos);
    }
    for(int i=1;i<=t;i++){
        int l,r;
        cin>>l>>r;
        if(ans[l]<=r)cout<<"1";
        else cout<<"0";
    }
}

 

以上是关于cf1143E 倍增好题!的主要内容,如果未能解决你的问题,请参考以下文章

线性dp,后缀处理——cf1016C好题

cf1061D 贪心+multiset 好题!

luogu CF708C Centroids 换根dp好题

luogu CF708C Centroids 换根dp好题

CF989C A Mist of Florescence 构造 思维好题 第八题

cf581F 依赖背包+临时数组 好题