BZOJ4943 [NOI2017] 蚯蚓
題目描述
蚯蚓幼兒園有nn?只蚯蚓。幼兒園園長神刀手為了管理方便,時常讓這些蚯蚓們列隊表演。
所有蚯蚓用從11?到nn?的連續正整數編號。每只蚯蚓的長度可以用一個正整數表示,根據入園要求,所有蚯蚓的長度都不超過66?。神刀手希望這些蚯蚓排成若干個隊伍,初始時,每只蚯蚓各自排成一個僅有一只蚯蚓的隊伍,該蚯蚓既在隊首,也在隊尾。
神刀手將會依次進行mm?次操作,每個操作都是以下三種操作中的一種:
給出ii?和jj?,令ii?號蚯蚓與jj?號蚯蚓所在的兩個隊伍合并為一個隊伍,具體來說,令jj?號蚯蚓緊挨在ii?號蚯蚓之后,其余蚯蚓保持隊伍的前后關系不變。
給出ii?,令ii?號蚯蚓與緊挨其后的一只蚯蚓分離為兩個隊伍,具體來說,在分離之后,ii?號蚯蚓在其中一個隊伍的隊尾,原本緊挨其后的那一只蚯蚓在另一個隊伍的隊首,其余蚯蚓保持隊伍的前后關系不變。
而f(t)f(t)?表示所有蚯蚓中,向后kk?數字串恰好為tt?的蚯蚓只數。
輸入輸出格式
輸入格式:
?
輸入文件的第一行有兩個正整數n,mn,m?,分別表示蚯蚓的只數與操作次數。
第二行包含nn?個不超過66?的正整數,依次表示編號為1, 2, \dots , n1,2,…,n?的蚯蚓的長度。
接下來mm?行,每行表示一個操作。每個操作的格式可以為:
-
1 i j?(1 \leqslant i, j \leqslant n)(1?i,j?n)?表示:令ii?號與jj?號蚯蚓所在的兩個隊伍合并為一個隊伍,新隊伍中,jj?號蚯蚓緊挨在ii?號蚯蚓之后。保證在此操作之前,ii?號蚯蚓在某個隊伍的隊尾,jj?號蚯蚓在某個隊伍的隊首,且兩只蚯蚓不在同一個隊伍中。
-
2 i?(1 \leqslant i \leqslant n)(1?i?n)?表示:令ii?號蚯蚓與緊挨其后一個蚯蚓分離為兩個隊伍。保證在此操作之前,ii?號蚯蚓不是某個隊伍的隊尾。
- 3 s k?(kk?為正整數,ss?為一個長度至少為kk?的數字串)表示:詢問ss?的每個長度為kk?的子串tt?的f(t)f(t)?的乘積,對998244353998244353?取模的結果。f(t)f(t)?的定義見題目描述。
同一行輸入的相鄰兩個元素之間,用恰好一個空格隔開。
輸入文件可能較大,請不要使用過于緩慢的讀入方式。
?
輸出格式:
?
依次對于每個形如3 s k的操作,輸出一行,僅包含一個整數,表示詢問的結果。
題目大意:
??? 一個初始全為單個元素的集合,支持合并,分裂,查詢s,k求出s所有長度為k的子串在現有的序列中出現的次數的乘積。
題解:
???? ①用鏈表記錄nxt[],pre[]來模擬分裂,合并;
???? ②考慮到k<=50,意思就是我們只需要維護長度在50以內串,外加查詢其出現的次數。而分裂操作c并不多,意味著合并也并不多。暴力維護即可:每次合并分裂時枚舉跨過斷點前后50位以內的串修改。
???? ③用hash散列表來修改和查詢,由于hash的模值比較大,無法開下所有v值,就可以將v類似于存邊存進v%sz里,每次修改和查詢暴力枚舉一遍,復雜度幾乎為O(1)
?
1 #pragma GCC optimize(2) 2 #include<cstdio> 3 #include<iostream> 4 #include<cstring> 5 #define N 200010 6 #define M 11000000 7 #define base 1000000007 8 #define mod 998244353 9 #define ull unsigned long long 10 using namespace std; 11 int n,m,pre[N],nxt[N]; 12 char tmp[M],*P = tmp,*s,a[N]; 13 ull H[M],pw[M]; 14 char gc(){ 15 static char *p1,*p2,s[1000000]; 16 if(p1==p2) p2=(p1=s)+fread(s,1,1000000,stdin); 17 return(p1==p2)?EOF:*p1++; 18 } 19 int rd(){ 20 int x = 0,f = 1; char c = gc(); 21 while(c<'0'||c>'9') {if(c=='-') f = -1; c = gc();} 22 while(c>='0'&&c<='9') {x = x * 10 + c - '0'; c = gc();} 23 return x * f; 24 } 25 int rd(char *c){ 26 char *st = c; 27 do *c = gc(); while(*c<'0'||*c>'9'); 28 do *++c = gc(); while(*c>='0'&&*c<='9'); 29 *c = 0; 30 return c - st; 31 } 32 struct Edge{ull v; int nt,w;}; 33 const int sz = 1e7; 34 struct HASH{ 35 Edge E[sz + 1]; int o,hd[sz + 1]; 36 int& adde(ull v){ 37 E[++o] = (Edge){v,hd[v%sz],0}; hd[v%sz] = o; 38 return E[o].w; 39 } 40 int& operator [] (ull v){ 41 for(int i = hd[v%sz];i;i=E[i].nt) 42 if(E[i].v==v) return E[i].w; 43 return adde(v); 44 } 45 int val(ull v){ 46 for(int i = hd[v%sz];i;i=E[i].nt) 47 if(E[i].v==v) return E[i].w; 48 return 0; 49 } 50 }Hash; 51 void cal(int y,int x){ 52 static char S[N]; int len = 0,fg; 53 int st;for(st = y;pre[st]&&len<=50;st = pre[st],len++); fg = ++len; 54 int ed;for(ed = y;nxt[ed]&&len<=100;ed = nxt[ed],len++); 55 len = 0; //S[++len] = a[st]; 56 for(int i = st;nxt[i];i = nxt[i]) S[++len] = a[i]; 57 S[++len] = a[ed]; 58 for(int i = 1;i <= len;i++) H[i] = H[i - 1]*base + S[i]; 59 for(int i = fg;i <= len;i++) 60 for(int j = max(i - 50,0);j < fg - 1;j++){ 61 Hash[H[i] - H[j] * pw[i - j]]+=x; 62 } 63 } 64 int main() 65 { //freopen("mzoj1112.in","r",stdin); 66 //freopen("mzoj1112.out","w",stdout); 67 n = rd(); m = rd(); 68 for(int i = pw[0] = 1;i < M;i++) pw[i] = pw[i - 1] * base; 69 for(int i = 1;i <= n;i++) Hash[a[i] = rd() + '0']++; 70 for(int i = 1,typ,x,y,len,k;i <= m;i++){ 71 typ = rd(); 72 if(typ==1) { 73 x = rd(); y = rd(); 74 pre[y] = x; nxt[x] = y; 75 cal(y,1); 76 } 77 else if(typ==2){ 78 x = rd(); y = nxt[x]; 79 cal(y,-1); 80 pre[y] = nxt[x] = 0; 81 } 82 else{ 83 s = P; len = rd(s+1); P += len + 2; k = rd(); 84 ull ans = 1; 85 for(int i = 1;i <= len;i++){ 86 H[i] = H[i - 1]*base + s[i]; 87 if(i>=k) { 88 ull temp = H[i] - H[i - k] * pw[k]; 89 ans = ans * Hash.val(temp) % mod; 90 } 91 } 92 printf("%llu\n",ans); 93 } 94 } 95 return 0; 96 }//by tkys_Austin;?
?
?
?????
轉載于:https://www.cnblogs.com/Paul-Guderian/p/8579870.html
總結
以上是生活随笔為你收集整理的BZOJ4943 [NOI2017] 蚯蚓的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue中key的作用
- 下一篇: python的学习笔记(0)之循环的使用