洛谷3823 [NOI2017] 蚯蚓排队 【哈希】
题目分析:
从$\sum|S|$入手。共考虑$\sum|S|$个$f(t)$。所以我们要一个对于每个$f(t)$在$O(1)$求解的算法。不难想到是哈希。
然后考虑分裂和合并操作。一次合并操作要考虑合并点之前的$O(k)$个点向后衔接的哈希值。共$O(k^2)$。看似超时实则不然。一个串最多$O(nk)$个哈希结果,所以均摊入手。
对于分裂和重合并不能均摊,所以多了一个$O(ck^2)$。
这题的合并和分裂只和合并点和分裂点有关,而这个信息是给出的,所以不需要额外使用数据结构维护结果。
时间复杂度$O(nk+mk+ck^2+\sum |s|)$
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std; const int maxsz = ;
const int maxn = ;
const int mod = ;
const int hmod1 = ;
const int hmod2 = ; int n,m,maxx;
int a[maxn],pts[maxn];
int ans[maxn],Num,nouse[],nuse[];
int hsh[hmod1+],Nxt[maxn*],real[maxn*],val[maxn*],hnum; struct query{ int cas;string str; int l,r; }Q[maxn]; int global = ; struct linktable{int pre[maxn>>],nxt[maxn>>];}T; void in(int &x){
char ch = getchar();
while(ch > '' || ch < '') ch = getchar();
while(ch <= '' && ch >= '') x = x*+ch-'',ch = getchar();
} void readstring(string &str){
char ch = getchar();
while(ch > '' || ch < '') ch =getchar();
while(ch <= '' && ch >= '') str.push_back(ch),ch=getchar();
} void read(){
in(n),in(m);
for(int i=;i<=n;i++) {in(a[i]);}
for(int i=;i<=m;i++){
in(Q[i].cas);
if(Q[i].cas == ) in(Q[i].l),in(Q[i].r);
else if(Q[i].cas == ) in(Q[i].l);
else {readstring(Q[i].str),in(Q[i].l);Q[i].r = ++Num;maxx = max(maxx,Q[i].l);}
}
} int imnum[],numnum; void Add_hash(int a1,int a2,int dr){
int p1 = hsh[a1];
while(true) {
if(real[p1] == a2) {val[p1]+=dr;return;}
if(Nxt[p1]) p1 = Nxt[p1];
else break;
}
hnum++; if(p1) Nxt[p1] = hnum;
p1 = hnum; val[p1] = ; real[p1] = a2;
if(!hsh[a1]) hsh[a1] = p1;
} void buildnew(int lft,int rgt,int dr){
numnum = ;int now = lft;
while(true){
if(numnum == maxx-) break;
imnum[++numnum] = a[now];
if(T.pre[now]) now = T.pre[now];
else break;
}
now = rgt;long long um = ,vm = ;
for(int i=;i<=numnum;i++){
um = (1ll*nouse[i-]*imnum[i]+um)%hmod1;
vm = (1ll*nuse[i-]*imnum[i]+vm)%hmod2;
long long r1 = um,r2 = vm;
for(int j=i+,jj=rgt;j<=maxx;j++){
r1 = (r1*+a[jj])%hmod1; r2 = (r2*+a[jj])%hmod2;
Add_hash(r1,r2,dr); if(!T.nxt[jj])break; jj = T.nxt[jj];
global++;
}
}
} void link(int lft,int rgt){
buildnew(lft,rgt,);
T.nxt[lft] = rgt; T.pre[rgt] = lft;
} void cut(int place){
buildnew(place,T.nxt[place],-);
T.pre[T.nxt[place]] = ; T.nxt[place] = ;
} int COUNT(int alpha,int beta){
int fw = ;
for(int i=hsh[alpha];i;i=Nxt[i]){
if(real[i] != beta) continue;
fw += val[i];
}
return fw;
} void work(){
for(int i=;i<=n;i++) nouse[a[i]]++;
for(int i=;i<=m;i++){
if(Q[i].cas != || Q[i].l != ) continue;
int fw = ; for(int j=;j<Q[i].str.length();j++){fw = (1ll*fw*nouse[Q[i].str[j]-''])%mod;}
ans[Q[i].r] = fw;
}
memset(nouse,,sizeof(nouse)); nouse[] = ;nuse[] = ;
for(int i=;i<=;i++) nouse[i] = (nouse[i-]*10ll)%hmod1,nuse[i] = (nuse[i-]*10ll)%hmod2; for(int i=;i<=m;i++){
if(Q[i].cas == ) link(Q[i].l,Q[i].r);
else if(Q[i].cas == ) cut(Q[i].l);
else{
if(Q[i].l == ) continue;
int fw = ;long long hres1=,hres2 = ;
for(int j=;j<Q[i].l;j++){
hres1 = hres1*+Q[i].str[j]-'';
hres2 = hres2*+Q[i].str[j]-'';
hres1 %= hmod1; hres2 %= hmod2;
}
fw = (1ll*fw*COUNT(hres1,hres2))%mod;
for(int j=Q[i].l;j<Q[i].str.length();j++){
hres1 -= ((Q[i].str[j-Q[i].l]-'')*nouse[Q[i].l-])%hmod1;
hres1 += hmod1; hres1 %= hmod1;
hres2 -= ((Q[i].str[j-Q[i].l]-'')*nuse[Q[i].l-])%hmod2;
hres2 += hmod2; hres2 %= hmod2;
hres1 = (hres1*+Q[i].str[j]-'');hres1 %= hmod1;
hres2 = (hres2*+Q[i].str[j]-'');hres2 %= hmod2;
fw = (1ll*fw*COUNT(hres1,hres2))%mod;
}
ans[Q[i].r] = fw;
}
}
for(int i=;i<=Num;i++) printf("%d\n",ans[i]);
} int main(){
read();
work();
return ;
}
洛谷3823 [NOI2017] 蚯蚓排队 【哈希】的更多相关文章
- 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】
题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...
- P3823_[NOI2017]蚯蚓排队 哈希+脑子
之前就写过一遍,今天却写挂了,查了半天发现是数组名写错啦$qwq$ 观察到$K$很小,所以使得我们可以哈希(怎么什么都能哈希$qwq$).我们把长度小于等于$50$的子串扔到哈希表里,并统计出现次数, ...
- 【BZOJ】4721: [Noip2016]蚯蚓 / 【洛谷】P2827 蚯蚓(单调队列)
Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮 ...
- BZOJ4943 & 洛谷3823 & UOJ315:[NOI2017]蚯蚓排队——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4943 http://uoj.ac/problem/315 https://www.luogu.or ...
- [NOI2017]蚯蚓排队 hash
题面:洛谷 题解: 我们暴力维护当前所有队伍内的所有子串(长度k = 1 ~ 50)的出现次数. 把每个子串都用一个hash值来表示,每次改变队伍形态都用双向链表维护,并暴力更新出现次数. 现在考虑复 ...
- 【题解】洛谷P2827 [NOIP2016TG] 蚯蚓(优先队列)
题目来源:洛谷P2827 思路 阅读理解题 一开始以为是裸的优先队列而已 但是发现维护一个切开并且其他的要分别加上一个值很不方便 而且如果直接用优先队列会TLE3到4个点 自测85分 所以我们需要发现 ...
- 洛谷3825 [NOI2017]游戏 2-sat
原文链接http://www.cnblogs.com/zhouzhendong/p/8146041.html 题目传送门 - 洛谷3825 题解 我们考虑到地图中x的个数很少,最多只有8个. 所以我们 ...
- 【题解】洛谷P1966 [NOIP2013TG] 火柴排队(树状数组+逆序对)
次元传送门:洛谷P1966 思路 显然在两排中 每排第i小的分别对应就可取得最小值(对此不给予证明懒) 所以我们只在意两排的火柴是第几根 高度只需要用来进行排序(先把两个序列改成有序的方便离散化) 因 ...
- 洛谷 P3825 [NOI2017]游戏 【2-SAT+状压】
UOJ和洛谷上能A,bzoj 8ms即WA,现在也不是知道为啥--因为我太弱了 先看数据范围发现d非常小,自然想到了状压. 所以先假装都是只能跑两种车的,这显然就是个2-SAT问题了:对于x场没有hx ...
随机推荐
- 使用PHPExcel将数据导出至Excel
安装类库 从GitHub上下载PHPExcel类库 地址:https://github.com/PHPOffice/PHPExcel 解压后将Classes文件夹移动到ThinkPHP的extend目 ...
- redis-trib.rb命令详解
redis-trib.rb是官方提供的Redis Cluster的管理工具,无需额外下载,默认位于源码包的src目录下,但因该工具是用ruby开发的,所以需要准备相关的依赖环境. 准备redis-tr ...
- jdk1.8之线程中断
在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止.中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 " 线程中断不会使线 ...
- 基于HTTP可供浏览器调用的本地打印程序
之前给公司做打印都是用ActiveX控件,只支持IE浏览器,最近需要支持谷歌,又不想去学谷歌插件编写,于是就用本地启动一个http服务器来供浏览器调用(写成windows服务更好),同事用了都说好(笑 ...
- 计算机名称改名之后,tfs连接问题
计算机名称改名之后,我们发现tfs连接会有问题 打开vs下的“开发人员命令提示”执行下面两条语句: 1.tf workspaces 2.tf workspaces /collection:http:/ ...
- poj2449 第k短路
题目链接 学习博客:https://blog.csdn.net/Z_Mendez/article/details/47057461 k短路没有我想象的那么难,还是很容易理解的 求s点到t点的第k短路径 ...
- atcoderI - Coins ( 概率DP)
I - Coins Time Limit: 2 sec / Memory Limit: 1024 MB Score : 100100 points Problem Statement Let NN b ...
- Vue使用的一些实例
1.实现歌曲的点击切换. <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- array_filter、array_walk、array_map的区别
<?php $arr=array( 1,2,3,4,5,6 ); function filter($var){ if($var%2==0) return true; } $data=array_ ...
- MySQL 的两个特殊属性 unsigned与 zerofill
1 unsigned unsigned 就是将数字类型无符号化, 例如 int 型的范围:-2^31 ~ 2^31 - 1,而unsigned int的范围:0 ~ 2^32.看起来unsigned ...