zoukankan      html  css  js  c++  java
  • 2019.11.11 洛谷月赛t3

    题目背景

    由于Y校的老师非常毒瘤,要求(zhouwc)(csp)考前最后(3)天参加期中考,(zhouwc)非常生气,决定消极考试,以涂完卡但全错为目标。现在(retcarizy)(zhouwc)太可怜了,想要帮(zhouwc)解决一个问题,但他自己又太忙了,咕咕咕,于是就把问题甩给了你。

    题目描述

    给你一个长度为(n)的字符串(S)

    (m)个操作,保证(mleq n)

    你还有一个字符串(T),刚开始为空。

    共有两种操作。

    第一种操作:

    在字符串(T)的末尾加上一个字符。

    第二种操作:

    在字符串(T)的开头加上一个字符。

    每次操作完成后要求输出有几个(l in [1,T.size])满足以下条件:

    对于(forall i in [1,l])(T_{T.size-l+i} e S_{i})

    (Tip:)字符串下标从(1)开始。(T.size)表示(T)的长度。

    输入格式

    第一行两个正整数(n,m)

    第二行(n)个正整数,用空格隔开,第(i)个整数表示(S_i)

    接下来(m)行,每行两个数字(opt,ch)(opt=0)表示在(T)的末尾加一个字符(ch),(opt=1)表示在(T)的开头加一个字符(ch)

    输出格式

    (m)行,每行一个非负整数表示第(m)操作后的输出。

    输入输出样例

    输入 #1

    10 3
    1 2 3 1 2 3 2 3 2 3
    0 1
    1 2
    0 3
    

    输出 #1

    0
    1
    1
    

    说明/提示

    注意:本题采用捆绑测试,只有当你通过一个subtask的所有点后,你才能拿到这个subtask的分数

    对于所有的数据 (n leq 10^6,m leq 3.3333 imes 10^4,|sum|leq10^3,S_i in [1,|sum|])((sum)表示字符集)

    (subtask1(17\%)):(m leq 333)

    (subtask2(33\%):m leq 3333)

    (subtask3(20\%):|sum|leq2∣)

    (subtask4(30\%):)无特殊条件

    样例解释:

    第一次操作后,(T=“1”),

    (l=1)(T[1]=S[1]),所以答案为你不jjgvfj(0)

    第二次操作后,(T=“21”),

    (l=1)时,(T[2]=S[1])

    (l=2)时,(T[1]!=S[1])(T[2]!=S[2]),所以答案为(1)

    第三次操作后,(T=“213”),

    (l=1)时,(T[3]!=S[1]);

    (l=2)时,(T[2]=S[1]);

    (l=3)时,(T[3]=S[3]),所以答案为(1)

    (O(m^3))的做法很容易想,按照题意模拟即可。预计得分(17pts)

    对于(O(m^2))的做法,因为这个题实际上是查找(S)的前(l)个和(T)的后(l)个是否严格不相等,我们考虑记录(dp[l])表示在上述意义下(l)是否合法。容易知道,在(T)串最后插入一个字符时,因为(S)串始终不变,(T)串的最后(l)个字符从原本(T)串的后(l)个字符变成了原本(T)串的后(l-1)个字符加上新加入的字符,所以为了比较新的(T)串后(l)个字符是否合法,我们只需要比较新字符、原本(T)串的后(l-1)个字符是否相等即可。即(dp[i]=dp[i-1]|(ch==S[i]))。这样,对于每个加入的字符,只需要用(O(1))的复杂度检查每个枚举到的(l)是否合法即可。

    (T)串最前面插入一个字符时,因为原本所有的合法的(l)依然没有变化,只是增加了一个新的(l),所以我们只需暴力(check)新加入的答案(l),对于每一位枚举是否不同即可。

    时间复杂度(O(m^2)),预计得分(50pts)。是我在考场上想出来的方法。

    考虑优化(O(m^2))的做法,我们找到了状压神器——(bitset),它可以将复杂度优化到原来的(frac{1}{32})。如果常数优秀一些这个方法可以过。

    考虑刚才的方法算过了哪些不可能合法的状态,我们知道所有的字符其存在位置都是独立的,所以我们用一个(bitset)数组(id[i])记录字符(i)在哪些位置上出现过。只要加入的新数(dt)对应的位置是(id[dt])(1)的位置,则该状态肯定不合法。

    所以这样优化的关键在于同时算出了所有合法的状态。所以我们用(f)的第(i)位的(0/1)表示后缀长度为(i)时是否合法。

    如果在(T)串尾部加入新的字符,则对于长度是(i)的情况一定是由(i-1)的情况和新加入位的情况同时转移来(见上述(O(n^2))做法),而所有新加入的位对应与(S)串中哪些位相同已经存储好,假设加入的字符是(dt),则(f=(f<<1)|id[dt])

    如果在(T)串头部加入新的字符,设原来(T)串有效的后缀长度有(l)位,则新的(T)串后(l)位是否合法状态不变,所以新旧(T)串前面(l)位答案一样;

    (T)串头部插入新字符时,我们发现遇到了一些新的问题:

    第一,我们发现在头部加入字符时,后面的所有字符都往后移了一位。

    第二,我们需要比较加入的新字符和第一个字符是否相同。

    很明显困难在于解决第一个问题。因为我们如果要想比较移动之后的字符和(S)的关系,在不知道其它任何东西的情况下,需要另用一个(O(n))检查。

    解决这个问题的方法是一个非常重要的思想:费用提前。在每次从队尾加入一个字符时,我们将这个字符所能贡献到答案的所有位置一次存好。方法很简单,假设我们每次加进的字符是(dt),考虑这一位对应到(S)串的所有可能。如果(dt)对应到的某一位上(id[dt])在同样的位上恰好是(1),说明当队尾不断加入字符使当前这个(dt)恰好对应到刚才说的这一位上,则这样的方案肯定是不合法的。

    考虑如何进行这样的操作。假设(dt)是在第(i)位加入队列,则(dt)(T)结尾的长度是(i-1)。注意这里我们只讨论(T)序列结尾的费用提前,因为其它点情况和结尾一样。假设(dt)对应的(id)值在第(k)位上是(1),说明(dt)在取到第(k)位时整体一定不合法。这时(dt)距离队尾的距离是(l-1),所以(dt)的位置由队尾左移(i-1)位得到,所以当(dt)取到(k)时,队尾应该取到(k+l-1)位,但是注意是反着存的,所以:

    [f=f|(id[dt]<<x-1) ]

    上代码:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<bitset>
    using namespace std;
    int n,m,opt,S[1000005],dt;
    bitset<35005> f,id[1005],now;
    int read(){
        int ans=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')
            ch=getchar();
        while(ch<='9'&&ch>='0'){
            ans=ans*10+ch-'0';
            ch=getchar();
        }
        return ans;
    }
    int main(){
        n=read();
        m=read();
        for(int i=1;i<=n;i++)
            S[i]=read();
        for(int i=1;i<=m;i++)
            id[S[i]].set(i);
        now.set();
        for(int i=1;i<=m;i++){
            opt=read();
            dt=read();
            now.reset(i);
            if(opt==0)
                f=(f<<1)|id[dt];
            else
                f=f|(id[dt]<<(i-1));
            printf("%d
    ",(~(f|now)).count());
        }
        return 0;
    }
    
  • 相关阅读:
    php命令注入
    mysql事物
    安装php环境
    移除服务器缓存实例
    show user profile synchronization tools
    manual start user profile import
    JSON is undefined. Infopath Form People Picker in SharePoint 2013
    asp.net web 应用站点支持域账户登录
    Load sharepoint envirement by powershell
    sharepoint 2016 download
  • 原文地址:https://www.cnblogs.com/qxds/p/11837850.html
Copyright © 2011-2022 走看看