LOJ#2303. 「NOI2017」蚯蚓排队

$n \leq 200000$的$1 \leq a_i \leq 6$的蚯蚓,有三种操作:让一只队头蚯蚓接在一只队尾蚯蚓后面;让一队蚯蚓从某个蚯蚓后面断成两队;问:给个字符串,问他的。。算了你们直接看题吧

这什么沙雕题QAQ

所有询问的串只有$nk$种,把他们全丢进hash里面就好了。。注意双hash,一个用来当链表一个用来在链表里判重。

复杂度的话,只考虑合并是$nk$的(相当于把所有串算一次),而拆分是$ck^2$的,拆对合并的复杂度影响是跟拆本身复杂度一样的。

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 //#include<math.h>
  5 //#include<set>
  6 //#include<queue>
  7 //#include<bitset>
  8 //#include<vector>
  9 #include<algorithm>
 10 #include<stdlib.h>
 11 using namespace std;
 12 
 13 #define LL long long
 14 int qread()
 15 {
 16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
 17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
 18 }
 19 
 20 //Pay attention to '-' , LL and double of qread!!!!
 21 
 22 int n,m;
 23 #define maxn 200011
 24 #define maxh 1000007
 25 int a[maxn],bb[55]; LL cc[55];
 26 
 27 struct Hash
 28 {
 29     struct Edge{LL to; int v,next;}edge[maxn*50]; int first[maxh],le;
 30     Hash() {le=2;}
 31     void in(LL x,int h,int v)
 32     {
 33         for (int i=first[h];i;i=edge[i].next)
 34         {
 35             Edge &e=edge[i];
 36             if (e.to==x) {e.v+=v; return;}
 37         }
 38         Edge &e=edge[le]; e.to=x; e.v=1; e.next=first[h]; first[h]=le++;
 39     }
 40     int find(LL x,int h)
 41     {
 42         for (int i=first[h];i;i=edge[i].next)
 43         {
 44             Edge &e=edge[i];
 45             if (e.to==x) return e.v;
 46         }
 47         return 0;
 48     }
 49 }h;
 50 
 51 int Nxt[maxn],Pre[maxn];
 52 char s[maxn*50]; int len;
 53 int main()
 54 {
 55     bb[0]=1; for (int i=1;i<=50;i++) bb[i]=bb[i-1]*7%maxh;
 56     cc[0]=1; for (int i=1;i<=50;i++) cc[i]=cc[i-1]*7;
 57     n=qread(); m=qread();
 58     for (int i=1;i<=n;i++) {Pre[i]=Nxt[i]=0; a[i]=qread(); h.in(a[i],a[i],1);}
 59     int op; char c; int x,y;
 60     while (m--)
 61     {
 62         op=qread();
 63         if (op==1)
 64         {
 65             x=qread(); y=qread();
 66             Nxt[x]=y; Pre[y]=x;
 67             LL B=0,C=0;
 68             for (int i=x,cnt=49,w=0;cnt && i;i=Pre[i],w++,cnt--)
 69             {
 70                 B=(B+1ll*a[i]*bb[w])%maxh;
 71                 C=C+1ll*a[i]*cc[w];
 72                 LL nb=B,nc=C;
 73                 for (int j=y,k=1;j && k<=cnt;j=Nxt[j],k++)
 74                 {
 75                     nb=(nb*7+a[j])%maxh;
 76                     nc=nc*7+a[j];
 77                     h.in(nc,nb,1);
 78                 }
 79             }
 80         }
 81         else if (op==2)
 82         {
 83             x=qread(); y=Nxt[x];
 84             Nxt[x]=0; Pre[y]=0;
 85             LL B=0,C=0;
 86             for (int i=x,cnt=49,w=0;cnt && i;i=Pre[i],w++,cnt--)
 87             {
 88                 B=(B+1ll*a[i]*bb[w])%maxh;
 89                 C=C+1ll*a[i]*cc[w];
 90                 LL nb=B,nc=C;
 91                 for (int j=y,k=1;j && k<=cnt;j=Nxt[j],k++)
 92                 {
 93                     nb=(nb*7+a[j])%maxh;
 94                     nc=nc*7+a[j];
 95                     h.in(nc,nb,-1);
 96                 }
 97             }
 98         }
 99         else if (op==3)
100         {
101             len=0;
102             while ((c=getchar())<'0' || c>'9');
103             do s[++len]=c; while ((c=getchar())>='0' && c<='9');
104             x=qread();
105             LL B=0,C=0;
106             for (int i=1;i<x;i++) B=(B*7+s[i]-'0')%maxh,C=C*7+s[i]-'0';
107             int ans=1;
108             for (int i=x;i<=len;i++)
109             {
110                 B=(B*7+s[i]-'0')%maxh; C=C*7+s[i]-'0';
111                 ans=1ll*ans*h.find(C,B)%998244353;
112                 B=(B-(s[i-x+1]-'0')*bb[x-1])%maxh+maxh; B%=maxh;
113                 C=C-(s[i-x+1]-'0')*cc[x-1];
114             }
115             printf("%d\n",ans);
116         }
117     }
118     return 0;
119 }
View Code

 

posted @ 2018-06-20 20:11  Blue233333  阅读(272)  评论(0编辑  收藏  举报