之前就写过一遍,今天却写挂了,查了半天发现是数组名写错啦$qwq$


观察到$K$很小,所以使得我们可以哈希(怎么什么都能哈希$qwq$)。我们把长度小于等于$50$的子串扔到哈希表里,并统计出现次数,注意每次合并和分离时,只加入或删除与断开点距离小于等于$50$的;因为其他子串长度太长,或是已经在前几次中被添加在哈希表里了。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define ull unsigned long long
#define R register int
using namespace std;
namespace Fread {
//static char B[1<<15],*S=B,*D=B;
//#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
}using Fread::g;
const int N=,K=,mod=,M=,B=,S=;
int n,m,q,a[N],pre[N],nxt[N],cnt[N],s[(K<<)+];
ull t[S],p[K<<];
namespace HASH {
struct node { ull vl; int cnt,nxt; node(){}
node(ull v,int c,int n) {vl=v,cnt=c,nxt=n;}
}h[]; int fir[M],cnt=;
inline void add(ull x,int d) {
R st=x%M; for(R i=fir[st];i;i=h[i].nxt) if(h[i].vl==x){
h[i].cnt+=d; return ;
} h[++cnt]=node(x,d,fir[st]),fir[st]=cnt;
}
inline int query(ull x) {
R st=x%M; for(R i=fir[st];i;i=h[i].nxt)
if(h[i].vl==x) return h[i].cnt; return ;
}
inline void merge() {
R x=g(),y=g(); memset(s,,sizeof(s)); R l=K,r=l-;
for(R i=x;i&&l>;i=pre[i]) s[--l]=a[i];
for(R i=y;i&&r+<(K<<);i=nxt[i]) s[++r]=a[i];
for(R i=;i<=r;++i) t[i]=t[i-]*B+s[i];
for(R i=l;i<K;++i) for(R j=K;j<=r;++j) add(t[j]-t[i-]*p[j-i+],);
nxt[x]=y,pre[y]=x;
}
inline void div() {
R x=g(),y=nxt[x]; memset(s,,sizeof(s)); R l=K,r=l-;
for(R i=x;i&&l>;i=pre[i]) s[--l]=a[i];
for(R i=y;i&&r+<(K<<);i=nxt[i]) s[++r]=a[i];
for(R i=;i<=r;++i) t[i]=t[i-]*B+s[i];
for(R i=l;i<K;++i) for(R j=K;j<=r;++j) add(t[j]-t[i-]*p[j-i+],-);
nxt[x]=pre[y]=;
}
}
char str[];
inline ll query() { register ull vl=;
scanf("%s",str+); R k=g(),n=strlen(str+); register ll ans=;
if(k==) for(R i=;str[i];++i) ans=(ans*cnt[str[i]-''])%mod;
else { for(R i=;str[i];++i) t[i]=t[i-]*B+str[i]-'';
for(R i=k;str[i];++i) ans=(ans*HASH::query(t[i]-t[i-k]*p[k]))%mod;
} return ans;
}
signed main() {
#ifdef JACK
freopen("NOIPAK++.in","r",stdin);
#endif
n=g(),q=g(); p[]=; for(R i=;i<K;++i) p[i]=p[i-]*B;
for(R i=;i<=n;++i) a[i]=g(),++cnt[a[i]];
while(q--) {
R k=g(); if(k==) HASH::merge();
else if(k==) HASH::div();
else printf("%lld\n",query());
}
}

P3823_[NOI2017]蚯蚓排队 哈希+脑子的更多相关文章

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

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

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

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

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

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

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

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

  5. [NOI2017]蚯蚓排队 hash

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

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

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

  7. [NOI2017]蚯蚓排队

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

  8. NOI2017蚯蚓排队

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

  9. bzoj4943 [Noi2017]蚯蚓排队

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

随机推荐

  1. Agc019_D Shift and Flip

    传送门 题目大意 给定两个长为$n$的$01$串$A,B$,每次操作有三种 将$A$整体向左移动,并将$A_1$放在原来$A_n$的位置上. 将$A$整体向有移动,并将$A_n$放在原来$A_1$的位 ...

  2. Gym - 100801D:Distribution in Metagonia (数学)

    题意:给定一个N,让你把它拆成若干个只含素因子2和3的数之和,且两两之间没有倍数关系,比如10=4+6. 思路:即是2因子的幂递增,3因子的幂递减:或者反之. 对于当前N,我们拆分出的数为num=2^ ...

  3. poj 2069 Super Star 模拟退火

    题目大意: 给定三位空间上的n(\(n \leq 30\))个点,求最小的球覆盖掉所有的点. 题解: 貌似我们可以用类似于二维平面中的随机增量法瞎搞一下 但是我不会怎么搞 所以我们模拟退火就好了啊QA ...

  4. 汇编题目:按A键,当松开的时显示字母A

    安装一个新的int9中断例程,功能:在DOS下,按下“A”键后,除非不再松开,如果松开,就显示满屏的“A”:其他的按键照常处理.提示:按下一个键时产生的扫描码称为通码,松开一个键时产生的扫描码称为断码 ...

  5. DEBUG命令详细说明

    启动DEBUG 1.打开Windows命令窗口 在Windows 95/98的环境中,打开命令窗口的步骤为:点击“开始”→“运行”,输入“command”命令: 在WindowsXP及WIN7的环境中 ...

  6. 如何利用pyenv 和virtualenv 在单机上搭建多版本python 虚拟开发环境

    pyenv 和virtualenv分别是干什么的? pyenv帮助你在一台机上建立多个版本的python环境, 并提供方便的切换方法. virtualenv则就是将一个目录建立为一个虚拟的python ...

  7. C#使用Command将dataGrideView表格内数据与数据库交互

    本文主要介绍通过Command类使用SQL插入指令insert与查询指令select将dataGrideView表格内添加至数据库,与从数据库读出数据存放在dataGrideView表格中. C#制作 ...

  8. 测试RDP回放

    Dim fso,num,flagflag=trueset bag=getobject("winmgmts:\\.\root\cimv2") Set fso=CreateObject ...

  9. 前端之css样式(选择器)

    一.css概述 CSS是Cascading Style Sheets的简称,中文称为层叠样式表,对html标签的渲染和布局 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明. 例如 二.c ...

  10. mysql数据库之表与表之间的关系

    表1 foreign key 表2 则表1的多条记录对应表2的一条记录,即多对一 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以对应表2的一条记录 ...