ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOI 2017 题目选做

2022-05-02 17:31:44  阅读:191  来源: 互联网

标签:选做 NOI int tt h1 h2 read 2017 op


蚯蚓排队

题目描述

点此看题

解法

做法是显然的,合并的时候把 \(k^2\) 个影响到的串暴力修改即可,使用 \(\tt hash\) 的话就很方便查询。

时间复杂度 \(O(n\cdot k^2+|s|)\) 好像过不去,但是注意到还有 \(c\leq 1000\) 这个限制。考虑没有分裂操作时,由于只有 \(O(nk)\) 个有效串,那么根据势能法时间复杂度 \(O(nk)\),操作每次分裂最多让势能增加 \(O(k^2)\),所以总时间复杂度 \(O(n\cdot k+c\cdot k^2+|s|)\)

但是突然发现我不会手写 \(\tt Hash\) 表(我好菜),于是问了天天写 \(\tt Hash\) 的 \(\tt dym\) 大佬。发现只需要对哈希值再哈希一遍,限制到一个较小的范围内(比如 \(10^7+7\)),然后用前向星维护,插入和查询都可以暴力扫描,期望单次时间复杂度就能做到 \(O(1)\)

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 200005;
const int p = 1e7+7;
const int MOD = 998244353;
#define ull unsigned long long
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,tot,f[p+5],a[M],h1[M],H1[M],b1[M],pre[M],nxt[M];
ull h2[M],H2[M],b2[M];char s[p];
struct edge{ull h2;int c,L,next;}e[M*55];
void add(int L,int h1,ull h2,int c)
{
	//printf(">> %d %d %u %d\n",L,h1,h2,c);
	for(int i=f[h1];i;i=e[i].next) if(e[i].h2==h2)
		{e[i].c+=c;return ;}
	e[++tot]=edge{h2,c,L,f[h1]},f[h1]=tot;
}
int ask(int L,int h1,ull h2)
{
	for(int i=f[h1];i;i=e[i].next)
		if(e[i].L==L && e[i].h2==h2) return e[i].c;
	return 0;
}
void work()
{
	int op=read();
	if(op==1 || op==2)
	{
		int x=read(),y=0,A=0,B=0,f=(op==1)?1:-1;
		y=(op==1)?read():nxt[x];
		for(int i=1,t=x;i<=50 && t;i++,t=pre[t],A++)
			h1[i]=(h1[i-1]+a[t]*b1[i-1])%p,h2[i]=h2[i-1]+a[t]*b2[i-1];
		for(int i=1,t=y;i<=50 && t;i++,t=nxt[t],B++)
			H1[i]=(H1[i-1]*13+a[t])%p,H2[i]=H2[i-1]*371+a[t];
		for(int l=2;l<=50 && l<=A+B;l++)
			for(int i=1;i<l && i<=A;i++) if(l-i<=B)
				add(l,(1ll*h1[i]*b1[l-i]+H1[l-i])%p
					,h2[i]*b2[l-i]+H2[l-i],f);
		if(op==1) nxt[x]=y,pre[y]=x;
		else nxt[x]=pre[y]=0;
		return ;
	} 
	scanf("%s",s+1);
	int l=strlen(s+1),k=read(),h1=0,ans=1;ull h2=0;
	for(int i=1;i<=l;i++) s[i]-='0';
	for(int i=1;i<=k;i++) h1=(h1*13+s[i])%p,h2=h2*371+s[i];
	for(int i=k;i<=l;i++)
	{
		ans=1ll*ans*ask(k,h1,h2)%MOD;
		if(ans==0) break;
		h1=(h1-1ll*s[i-k+1]*b1[k-1]%p)*13+s[i+1];
		h1=(h1%p+p)%p;
		h2=(h2-s[i-k+1]*b2[k-1])*371+s[i+1];
	}
	printf("%d\n",ans);
}
signed main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++)
		a[i]=read(),add(1,a[i],a[i],1);
	for(int i=b1[0]=b2[0]=1;i<=50;i++)
		b1[i]=b1[i-1]*13%p,b2[i]=b2[i-1]*371;
	while(m--) work();
}

标签:选做,NOI,int,tt,h1,h2,read,2017,op
来源: https://www.cnblogs.com/C202044zxy/p/16216231.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有