zoukankan      html  css  js  c++  java
  • luogu3823 [NOI2017]蚯蚓排队

    [NOI2017]蚯蚓排队

    为什么我觉得T2比T1裸啊

    突破口是(kleq 50),我们可以直接维护当前串长(leq k)的所有子串的(hash)值,那么(3)操作的时间复杂度变成了(O(sum|S|))

    考虑如何维护(1,2)操作(其实1操作对此的暗示也十分明显),我们通过维护一个链表来进行快速合并和断开,每次合并或断开的时候直接(O(k^2))维护(hash)值的增减,冷静分析一下的话发现时间复杂度其实应该是(O((n+c)k^2))的,并且很明显那个(k^2)是跑不满的

    其实还是比较好写的

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<math.h>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef unsigned long long ull;
    const int N=200000;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define fir first
    #define sec second
    #define mp(a,b) make_pair(a,b)
    #define pb(a) push_back(a)
    #define maxd 998244353
    #define p 10000009
    #define bas 7
    #define eps 1e-8
    #define K 50
    struct node{
        int cnt,nxt;ull val;
    }hsh[20020000];
    int all=0,head[p+10];
    
    int n,m,num[200200],pre[200200],suf[200200];
    ull pw[200200];
    char s[10000200];
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    void insert(ull x,int val)
    {
        int u=x%p,i;
        for (i=head[u];i;i=hsh[i].nxt)
        {
            if (hsh[i].val==x)
            {
                hsh[i].cnt+=val;
                return;
            }
        }
        hsh[++all].val=x;hsh[all].cnt=val;hsh[all].nxt=head[u];head[u]=all;
    }
    
    int query(ull x)
    {
        int i,u=x%p;
        for (i=head[u];i;i=hsh[i].nxt)
        {
            if (hsh[i].val==x) return hsh[i].cnt;
        }
        return 0;
    }
    
    int main()
    {
        n=read();m=read();
        pw[0]=1;
        rep(i,1,N) pw[i]=pw[i-1]*bas;
        rep(i,1,n)
        {
            num[i]=read();
            insert(num[i],1);
        }
        while (m--)
        {
            int op=read();
            if (op==1)
            {
                int x=read(),y=read();
                pre[y]=x;suf[x]=y;
                int i,pcnt=1;ull now=0;
                for (i=x;i && pcnt<=K;i=pre[i],pcnt++)
                {
                    now+=(pw[pcnt-1]*num[i]);
                    ull tmp=now;int j,tot=pcnt+1;
                    for (j=y;j && tot<=K;j=suf[j],tot++)
                    {
                        tmp=tmp*bas+num[j];
                        insert(tmp,1);
                    }
                }
            }
            else if (op==2)
            {
                int x=read(),y=suf[x];
                pre[y]=0;suf[x]=0;
                int i,pcnt=1;ull now=0;
                for (i=x;i && pcnt<=K;i=pre[i],pcnt++)
                {
                    now+=(pw[pcnt-1]*num[i]);
                    ull tmp=now;int j,tot=pcnt+1;
                    for (j=y;j && tot<=K;j=suf[j],tot++)
                    {
                        tmp=tmp*bas+num[j];
                        insert(tmp,-1);
                    }
                }
            }
            else
            {
                scanf("%s",s+1);
                int k=read(),len=strlen(s+1);
                ull now=0;ll ans=1;
                rep(i,1,len)
                {
                    //cout << now << endl;
                    now=now*bas+(s[i]-'0');
                    //cout << now << endl;
                    if (i>=k)
                    {
                        ans=ans*query(now)%maxd;
                        now-=((s[i-k+1]-'0')*pw[k-1]);
                    }
                    //cout << now << endl << endl;
                }
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    /*
    5 9
    3 1 3 5 3
    3 333135 2
    3 333135 1
    1 1 3
    1 2 5
    1 3 2
    1 5 4
    3 333135 2
    3 333135 1
    3 333135 3
     */
    
  • 相关阅读:
    周鸿祎笔录
    set multiset 集合实现众数的统计
    栈实现 汉诺塔 操作是否符合规范
    优先队列----解决排序问题
    字符串的应用(续一)
    优先队列 的实例(未完----待续)
    字符串的应用
    栈实现括号
    Jave垃圾回收算法
    Java 按代回收垃圾以及回收算法
  • 原文地址:https://www.cnblogs.com/encodetalker/p/11141334.html
Copyright © 2011-2022 走看看