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 }