1. 程式人生 > >BZOJ4943 NOI2017蚯蚓排隊(哈希+鏈表)

BZOJ4943 NOI2017蚯蚓排隊(哈希+鏈表)

getchar() space algorithm 哈希 所有 else case signed clas

能看懂題就能想到正解。維護所有長度不超過k的數字串的哈希值即可,用鏈表維護一下蚯蚓間連接情況。由於這樣的數字串至多只有nk個,計算哈希值的總復雜度為O(nk),而分裂的復雜度為O(ck^2),詢問復雜度為O(Σ|s|)。於是總復雜度為O(nk+ck^2+Σ|s|)。

BZOJ上46s過了,luoguT最後兩個點,加register結果過了倒數第二個點T了第19個點,太玄學了。卡不動常棄了。

// luogu-judger-enable-o2
#include<iostream> 
#include<cstdio>
#include<cmath>
#include
<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0;char c=getchar(); while (c<0||c>9) c=getchar(); while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x; } #define N 200010 #define S 10000010 #define
K 50 #define P 19260817 #define MOD 998244353 #define G 7 #define ul unsigned long long int n,m,POW[K+1][10]; struct data{int x,pre,nxt; }a[N]; int ch[S]; int map[P+10],cnt[P+10],nxt[P+10]; ul value[P+10],POWv[K+1][10]; void ins(int x,ul v) { if (!map[x]) map[x]=1,value[x]=v,cnt[x]=1; else {
int t; while (map[x]&&value[x]!=v) t=x,x=nxt[x]; if (map[x]) cnt[x]++; else map[x]=1,value[x]=v,cnt[x]=1,nxt[t]=x; } } void del(int x,ul v) { while (value[x]!=v) x=nxt[x]; cnt[x]--; } int query(int x,ul v) { while (map[x]&&value[x]!=v) x=nxt[x]; return cnt[x]; } int main() { n=read(),m=read(); for (int i=0;i<P-1;i++) nxt[i]=i+1;nxt[P-1]=0; for (int j=1;j<=9;j++) { POW[0][j]=j;for (int i=1;i<=K;i++) POW[i][j]=POW[i-1][j]*G%P; POWv[0][j]=j;for (int i=1;i<=K;i++) POWv[i][j]=POWv[i-1][j]*G; } for (int i=1;i<=n;i++) a[i].x=read(),ins(a[i].x,a[i].x); while (m--) { int op=read(); switch(op) { case 1: { int x=read(),y=read(); a[x].nxt=y,a[y].pre=x; for (int l=1,h=x;h&&l<K;h=a[h].pre,l++) { int hash=0;ul hashv=0; for (int i=1,t=h;i<=l;t=a[t].nxt,i++) hash=(hash*G+a[t].x)%P,hashv=hashv*G+a[t].x; for (int i=l+1,t=y;t&&i<=K;t=a[t].nxt,i++) { hash=(hash*G+a[t].x)%P,hashv=hashv*G+a[t].x; ins(hash,hashv); } } break; } case 2: { int x=read(),y=a[x].nxt; for (int l=1,h=x;h&&l<K;h=a[h].pre,l++) { int hash=0;ul hashv=0; for (int i=1,t=h;i<=l;t=a[t].nxt,i++) hash=(hash*G+a[t].x)%P,hashv=hashv*G+a[t].x; for (int i=l+1,t=y;t&&i<=K;t=a[t].nxt,i++) { hash=(hash*G+a[t].x)%P,hashv=hashv*G+a[t].x; del(hash,hashv); } } a[x].nxt=0;a[y].pre=0; break; } case 3: { char c=getchar();int l=0; while (c<0||c>9) c=getchar(); while (c>=0&&c<=9) ch[++l]=c^48,c=getchar(); int k=read(); int hash=0;ul hashv=0; for (int i=1;i<k;i++) hash=(hash*G+ch[i])%P,hashv=hashv*G+ch[i]; int ans=1; for (int i=k;i<=l;i++) { hash=(hash*G+ch[i]-POW[k][ch[i-k]]+P)%P, hashv=hashv*G+ch[i]-POWv[k][ch[i-k]]; ans=1ll*ans*query(hash,hashv)%MOD; } printf("%d\n",ans); } } } return 0; }

BZOJ4943 NOI2017蚯蚓排隊(哈希+鏈表)