您的位置:首页 > 其它

BZOJ4943 NOI2017蚯蚓排队(哈希+链表)

2018-07-30 21:55 302 查看

  能看懂题就能想到正解。维护所有长度不超过k的数字串的哈希值即可,用链表维护一下蚯蚓间连接情况。由于这样的数字串至多只有nk个,计算哈希值的总复杂度为O(nk),而分裂的复杂度为O(ck^2),询问复杂度为O(Σ|s|)。于是总复杂度为O(nk+ck^2+Σ|s|)。

  手写哈希注意插入元素时考虑清楚,如果没有哈希冲突不需要更新哈希使用的链表,所以特判一下。

#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
;
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;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: