• Codeforces Round #549 (Div. 2) 训练实录 (5/6)


    The Doors +0

    找出输入的01数列里,0或者1先出完的的下标。

    Nirvana +3

    输入n,求1到n的数字,哪个数逐位相乘的积最大,输出最大积。

    思路是按位比较,从低到高,依次把小位换成全9,判断一下。细节上容易出错,比如边界和减一的情况。要多加小心。

    Queen +0

    给一棵树,删除树中一些点,这些点的(C_i)权值是1,且直接的孩子也也是1。从小到大依次输出删除的编号。

    中间我以为是所有子孙的权值都要是1,幸好发现了。

    The Beatles /+0

    给一个(n cdot k) 的环,其中每(k)个点就是一个关键点,现在主人公要从某点出发,每次走(l)个距离,最后回到出发点。给出起点距离最近关键点的距离(a​),以及第二个到达的位置最近关键点的距离b。最少和最多需要多少次结束活动。

    1

    Lynyrd Skynyrd /+0

    看过了题解,需要一点倍增(binary lifting)的技巧,大多数时间都用来学倍增了。题意是给长度(n)的数组(p),长度(m)的数组(a),对(a)进行(q)次区间询问,每次判断区间内,是否存在子序列恰好等于(p)的某个cyclic shifts。
    cyclic shifts表示把p往左移动若干位,溢出的数依次插到右边。
    看上去还挺蒙的,解法要一步步来,首先找到(a[i])的最近的上一个数字(a[j])在什么位置,使得(a[j])(a[i])恰好是某对(p[k-1])(p[k]),我们把位置记作(pre[i])。那么我们可以对每个位置(i),往左找(a[i])作为结尾的匹配子序列的起点位置,如果能找到的话,我们可以对每个位置再记一个距离(i)最近的起点,每次询问就可以(O(1))解决。但是这个找起点的过程暴力做的话是显然(n*m)的,时间不允许,因为是连续找前驱的操作,可以用倍增来优化。

    我的代码有点丑,建议参考大佬代码(可能思路上也有所优化)

    //https://codeforces.com/contest/1143/problem/E
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 2e5+7;
    const int INF = 0x3f3f3f3f;
    int f[MAXN][(int)log(MAXN)+7];
    int pre[MAXN];
    int p[MAXN],a[MAXN];
    int posa[MAXN],posp[MAXN];
    int ans[MAXN];
    int n,m,q,k;
    
    int findpre(int u){
        int t=n-1;
        while(t&&u){
            for(int i=k;i>=0;i--){
                if((1<<i)<=t){
                    u=f[u][i];
                    t-=(1<<i);
                    break;
                }
            }
        }
        return u;
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
    
        //cout<<log10(100)<<endl;
        cin>>n>>m>>q;
    
        for(int i=1;i<=n;i++){
            cin>>p[i];
            posp[p[i]]=i;
        }
        for(int i=1;i<=m;i++){
            cin>>a[i];
            posa[a[i]]=i;
        }
        for(int pj,i=1;i<=m;i++){
            pj=(posp[a[i]]-1+n-1)%n+1;
            pre[i]=posa[p[pj]];
            posa[a[i]]=i;
        }
    
        for(int u=1;u<=m;u++){
            f[u][0]=pre[u]<u?pre[u]:0;
        }
    
        k=log(n)+1;
        for(int i=1;i<=k;i++){
            for(int u=1;u<=m;u++){
                f[u][i]=f[f[u][i-1]][i-1];
            }
        }
    
        for(int t,u=n;u<=m;u++){
            t=findpre(u);
            ans[u]=max(t,ans[u-1]);
        }
        for(int l,r,i=1;i<=q;i++){
            cin>>l>>r;
            if(ans[r]>=l)cout<<"1";
            else cout<<"0";
        }
        cout<<endl;
    
        return 0;
    }
    
    

    TBCD...还差一道,咕咕咕

    U2

  • 相关阅读:
    多校省选模拟33 C
    省选测试47 T2宝石(P5401 [CTS2019]珍珠) 题解
    省选测试39
    省选测试38
    省选测试37
    自嗨测试赛4
    自嗨测试赛3
    自嗨测试赛2
    自嗨测试赛1
    树状数组 学习笔记
  • 原文地址:https://www.cnblogs.com/tieway59/p/10639054.html
Copyright © 2020-2023  润新知