zoukankan      html  css  js  c++  java
  • 2016集训测试赛(二十四)Problem B: Prz

    Description

    Solution

    这道题有两个关键点:

    • 如何找到以原串某一个位置为结尾的某个子序列的最晚出现位置
    • 如何找到原串中某个位置之前的所有数字的最晚出现位置中的最大值

    第一个关键点: 我们注意到每个数字在(M)(L)中最多只会出现一次. 以(M)为例, 我们从前往后逐位在原串中匹配, 数组f[i]表示(M)的前(i)位在原串中当前位置之前的最晚出现位置. 假设当前数字(x)(M)中出现位置为(p), 则

    [f[p] = egin{cases} f[p] = i, p == 1 \ f[p] = f[p - 1], p > 1 end{cases} ]

    至于其他长度的子序列, 其最晚出现位置并不会发生变化.

    第二个关键点: 我们记录每个数字的最晚出现位置即可.

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    namespace Zeonfai
    {
        inline int getInt()
        {
            int a = 0, sgn = 1; char c;
            while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
            while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
            return a * sgn;
        }
    }
    const int N = (int)1e6, M = (int)1e6;
    int main()
    {
    
    #ifndef ONLINE_JUDGE
    
        freopen("prz.in", "r", stdin);
        freopen("prz.out", "w", stdout);
    
    #endif
    
        using namespace Zeonfai;
        int len = getInt(), m = getInt();
        static int a[N + 1], s[N + 1], t[N + 1];
        for(int i = 1; i <= len; ++ i) a[i] = getInt();
        int lenS = getInt(), lenT = getInt();
        for(int i = 1; i <= lenS; ++ i) s[i] = getInt();
        for(int i = 1; i <= lenT; ++ i) t[i] = getInt();
        static int mp[N + 1]; memset(mp, -1, sizeof(mp));
        for(int i = 1; i <= lenS; ++ i) mp[s[i]] = i;
        static int rec[N + 1]; memset(rec, -1, sizeof(rec));
        static int f[N + 1], g[N + 1];
        for(int i = 1; i <= len; ++ i)
        {
            if(~ mp[a[i]])
            {
                if(mp[a[i]] == 1) rec[mp[a[i]]] = i;
                else rec[mp[a[i]]] = rec[mp[a[i]] - 1];
            }
            f[i] = rec[lenS];
        }
        memset(mp, -1, sizeof(mp));
        for(int i = 1; i <= lenT; ++ i) mp[t[i]] = i;
        memset(rec, -1, sizeof(rec));
        for(int i = len; i; -- i)
        {
            if(~ mp[a[i]])
            {
                if(mp[a[i]] == 1) rec[mp[a[i]]] = i;
                else rec[mp[a[i]]] = rec[mp[a[i]] - 1];
            }
            g[i] = rec[lenT];
        }
        memset(mp, -1, sizeof(mp));
        for(int i = len; i; -- i) if(mp[a[i]] == -1) mp[a[i]] = i;
        static int lst[N + 1]; lst[0] = -1;
        for(int i = 1; i <= len; ++ i) lst[i] = max(mp[a[i]], lst[i - 1]);
        int cnt = 0; static int ans[N];
        for(int i = 1; i <= len; ++ i) if(~ f[i] && ~ g[i] && a[i] == s[lenS] && lst[f[i] - 1] > g[i]) ans[cnt ++] = i;
        printf("%d
    ", cnt);
        for(int i = 0; i < cnt; ++ i) printf("%d ", ans[i]);
    }
    
    
  • 相关阅读:
    window 窗口对象http://www.diybl.com/course/1_web/javascript/jsjs/2007104/76401.html
    Web开发中的Drag&Drop完全手册http://www.cnblogs.com/birdshome/archive/2006/07/22/457369.aspx
    [转载]window 的 setTimeout() 與 clearTimeout() 方法
    javascript this详解(转) http://www.cnblogs.com/felix2007/archive/2007/03/21/682670.html
    关闭浏览器弹出对话框事件onbeforeunload http://www.blogjava.net/jennyli/articles/82351.html
    页面跳转http://www.9ba.cn/post/235.html
    POJ 3667 Hotel
    hdu 2511 汉诺塔 X
    UESTC Another LCIS
    Hdu 1576 A/B
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7519029.html
Copyright © 2011-2022 走看看