原题链接

发现 k<=50 ,在插入和删除时最多会影响不超过 k2 个串,用链表实现插入和删除,然后只需用哈希表维护每个长度不超过k的串的出现次数,哈希的话可以先用比较大的范围的值处理冲突,再映射到1e8的桶里统计。

考虑复杂度。

首先在删除时由于保证了 c<=1000 所以这部分复杂度是O(ck2)的。

插入时,如果插入操作很慢只有可能是连接两个长度不小于k的串,而长度不小于k的串最多有n/k个,所以这部分复杂度是O(nk)的

所以总复杂度是O(nk+ck2+|s|)。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
using namespace std;
inline void read(int &re)
{
char ch=getchar();int g=1;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
re=0;
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
re*=g;
}
typedef long long ll;
typedef double db;
typedef unsigned long long ul;
const ul bas=7u;
const ll mod=998244353;
const ul mod2=99999971u;
const int N=200050;
int head[N],tail[N],cnt=0,nex[20050000],fir[100000000];
int num[20050000];
ul hax[20050000];
char leng[N]; inline ul qpow(ul a,int n)
{
ul ans=1;
for(;n;n>>=1,a=a*a) if(n&1) ans=ans*a;
return ans;
} inline void insert(ul x)
{
ul m=x%mod2;
int u=fir[m];
if(!u)
{
fir[m]=++cnt; hax[cnt]=x;
num[cnt]++; return ;
}
if(hax[u]==x) {num[u]++;return ;}
while(nex[u])
{
u=nex[u];
if(hax[u]==x) {num[u]++; return ;}
}
cnt++;
nex[u]=cnt;
hax[cnt]=x; num[cnt]++;
} inline void del(ul x)
{
ul m=x%mod2;
int u=fir[m];
while(u)
{
if(hax[u]==x) {num[u]--;return ;}
u=nex[u];
}
} inline int query(ul x)
{
ul m=x%mod2;
int u=fir[m];
while(u)
{
if(hax[u]==x) return num[u];
u=nex[u];
}
return 0;
}
char a[10000050];
int n,m; int main()
{
#ifndef ONLINE_JUDGE
freopen("queue.in","r",stdin);freopen("queue.out","w",stdout);
#endif
int i,j,opt,x,y,k;
read(n);read(m);
for(i=1;i<=n;++i)
{
read(opt),leng[i]=opt+48;
ul has=leng[i]-48u;
insert(has);
}
while(m--)
{
read(opt);
if(opt==1)
{
read(x);read(y);//--x y--
tail[x]=y;head[y]=x;
int u=x,v;
for(i=1;i<=50-2&&head[u];++i) u=head[u];
for(;u!=y;u=tail[u])
{
bool can=0;
v=u;
ul has=0;
has=leng[u]-48u;
for(i=1;i<50;++i)
{
v=tail[v];
if(!v) break;
has=has*bas+leng[v]-48u;
if(v==y||can)
{
can=1;
insert(has);
}
}
}
}
else if(opt==2) // --x || y--
{
read(x);
int u=x,v;
y=tail[x];
for(i=1;i<=50-2&&head[u];++i) u=head[u];
for(;u!=y;u=tail[u])
{
bool can=0;
v=u;
ul has=leng[u]-48u;
for(i=1;i<50;++i)
{
v=tail[v];
if(!v) break;
has=has*bas+leng[v]-48u;
if(v==y||can)
{
can=1;
del(has);
}
}
}
head[y]=0;tail[x]=0;
}
else
{
ll ans=1;
scanf("%s",a);read(k);
int len=strlen(a); ul has=0,powbas=qpow(bas,k-1);
for(i=0;i<k;++i) has=has*bas+a[i]-48u;
ans=ans*(ll)query(has);
for(i=1;i<=len-k;++i)
{
has=(has-(a[i-1]-48u)*powbas)*bas+a[i+k-1]-48u;
ans=ans*(ll)query(has)%mod;
}
printf("%lld\n",ans);
}
}
return 0;
}

NOI2017蚯蚓排队的更多相关文章

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

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

  2. [NOI2017]蚯蚓排队 hash

    题面:洛谷 题解: 我们暴力维护当前所有队伍内的所有子串(长度k = 1 ~ 50)的出现次数. 把每个子串都用一个hash值来表示,每次改变队伍形态都用双向链表维护,并暴力更新出现次数. 现在考虑复 ...

  3. BZOJ4943 & 洛谷3823 & UOJ315:[NOI2017]蚯蚓排队——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4943 http://uoj.ac/problem/315 https://www.luogu.or ...

  4. 洛谷3823 [NOI2017] 蚯蚓排队 【哈希】

    题目分析: 从$\sum|S|$入手.共考虑$\sum|S|$个$f(t)$.所以我们要一个对于每个$f(t)$在$O(1)$求解的算法.不难想到是哈希. 然后考虑分裂和合并操作.一次合并操作要考虑合 ...

  5. 【uoj#315/bzoj4943】[NOI2017]蚯蚓排队 Hash

    题目描述 给出 $n$ 个字符,初始每个字符单独成字符串.支持 $m$ 次操作,每次为一下三种之一: $1\ i\ j$ :将以 $i$ 结尾的串和以 $j$ 开头的串连到一起. $2\ i$ :将 ...

  6. bzoj4943 [Noi2017]蚯蚓排队

    题面:http://www.lydsy.com/JudgeOnline/upload/Noi2017D1.pdf 正解:字符串$hash$. 我在考场上写了个$map$的$hash$被卡成$40$分, ...

  7. P3823_[NOI2017]蚯蚓排队 哈希+脑子

    之前就写过一遍,今天却写挂了,查了半天发现是数组名写错啦$qwq$ 观察到$K$很小,所以使得我们可以哈希(怎么什么都能哈希$qwq$).我们把长度小于等于$50$的子串扔到哈希表里,并统计出现次数, ...

  8. 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】

    题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...

  9. [NOI2017]蚯蚓排队

    嘟嘟嘟 现在看来这道题还不是特别难. 别一看到字符串就想SAM 看到\(k\)很小,所以我们可以搞一个单次修改复杂度跟\(k\)有关的算法. 能想到,每一次断开或链接,最多只会影响\(k ^ 2\)个 ...

  10. [NOI2017]蚯蚓排队(链表+hash)

    这题看题面感觉挺玄学的,但其实会挂链式hash就能暴力切了,就是纸老虎,考察选手的语文水平.不过三年没写挂链hash也应该写一下了…… 首先模数设成自然溢出ull,然后挂链时的模数取2^24.然后就可 ...

随机推荐

  1. 结束语句之 break

    C 语言自学之 break Dome1: 找出0-50之间的所有素数,所谓素数就是只能被1和它本身整除的数字,比如:7,13,23等.                运行结果: 2  3  5  7 ...

  2. day19--Java集合02

    Java集合02 6.ArrayList ArrayList的注意事项: Permits all element , including null ,ArrayList 可以加入null ,并且可以加 ...

  3. Blazor VS Vue

    Vue--​​两分钟概述 Vue 是一个JavaScript 框架. 在其最简单的模式中,您可以简单地将核心 Vue 脚本包含在您的应用程序中,然后开始构建您的组件. 除此之外,对于更复杂的应用程序, ...

  4. Java SE 10 新增特性

    Java SE 10 新增特性 作者:Grey 原文地址:Java SE 10 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  5. xtrabackup增量备份MySQL-5.7操作说明

    下载工具 本方法利用xtrabackup二进制包,版本是2.4.26 # 从官网下载二进制包:wget https://downloads.percona.com/downloads/Percona- ...

  6. Linux的OpenLava配置

    OpenLava OpenLava是基于LSF早期的开源版本发展而来,其免费.开源.兼容IBM LSF的工作负载调度器.当你需要执行某项业务时候(比如跑渲染之类的),当有服务器处于空闲状态时候,可以直 ...

  7. Java开发学习(三十)----Maven聚合和继承解析

    一.聚合 分模块开发后,需要将这四个项目都安装到本地仓库,目前我们只能通过项目Maven面板的install来安装,并且需要安装四个,如果我们的项目足够多,那么一个个安装起来还是比较麻烦的 如果四个项 ...

  8. KingbaseES V8R6集群维护案例之--单实例数据迁移到集群案例

    案例说明: 生产环境是单实例,测试环境是集群,现需要将生产环境的数据迁移到集群中运行,本文档详细介绍了从单实例环境恢复数据到集群环境的操作步骤,可以作为生产环境迁移数据的参考. 适用版本: Kingb ...

  9. Springboot mybatis总结

    mybatis 总结 属性配置 1. mybatis.configuration.mapUnderscoreToCamelCase=true mapUnderscoreToCamelCase用于映射表 ...

  10. mybatis 输出sql日志

    logging.level.com.dsmp.server.core.pgsqldao=debug com.dsmp.server.core.pgsqldao 为包名