洛谷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 ...
随机推荐
- TensorFlow 使用变量共享
参考: https://www.tensorflow.org/programmers_guide/variable_scope 举例说明 TensorFlow中的变量一般就是模型的参数.当模型复杂的时 ...
- 不容错过的超赞项目管理PPT
不容错过的超赞项目管理PPT(转载) 大公司的一个好处,是各个领域都有牛人,可以为你提供经验分享交流.腾讯庞大的培训体系更是保证了:如果你想学点什么东西,你总可以学到.腾讯内部资源30页PPT曝光 — ...
- Python学习第三篇——访问列表部分元素
dongman =["huoying","sishen","si wang bi ji","pan ni de lu lu xiu ...
- C#设计模式之8:外观模式
外观模式 外观模式和适配器模式一样,都实现了接口改变,适配器模式是让一个接口转化成另外一个接口,而外观模式是让接口变得更简单. 先来看一下需求: 外观模式没有封装子系统的类,外观只是提供一个统一的接口 ...
- Java中有关Null的9件事(转)
对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认 ...
- 剑指offer(20)二叉搜索树与双向表
题目: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路一:递归法 1.将左子树构造成双链表,并返回链表头节点. 2.定位至左子 ...
- synchronized无法禁止指令重排序的证明
package demo.reorder; import java.util.concurrent.ExecutorService; import java.util.concurrent.Execu ...
- 使用synchronized 实现ReentrantLock(美团面试题目)
刚看到这个题目的时候无从下手,因为觉得synchronized和lock在加锁的方式上有很大不同,比如,看看正常情况下synchronized时如何加锁的. 方式一: public synchroni ...
- 【Spring】——声明式事务配置详解
项目中用到了spring的事务: @Transactional(rollbackFor = Exception.class, transactionManager = "zebraTrans ...
- 老男孩python学习自修第十三天【md5加密】
示例代码如下: hashlib_test.py #!/usr/bin/env python # _*_ coding:UTF-8 _*_ import hashlib def genPasswd(na ...