博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ4943 & 洛谷3823 & UOJ315:[NOI2017]蚯蚓排队——题解
阅读量:6546 次
发布时间:2019-06-24

本文共 2449 字,大约阅读时间需要 8 分钟。

题面太长自己看吧orz。

参考:洛谷题解。

用链表暴力维护每个蚯蚓,每次合并和分离只对k*k的元素有影响,哈希一下存起来query时候比较就好了。

没了。

(具体复杂度我不会证明,以及bzoj卡空间,正常的哈希表空间总觉得不能开如代码所示的这么小。)

(自然溢出hash真的块)

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;typedef long long ll;typedef unsigned long long ull;const int N=2e5+5;const int K=50;const int mod=998244353;const int p=19260817;const int B=13;inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X;}struct node{ int nxt,cnt; ll w;}e[21000000];char s[10000005];int n,m,cnt,head[p+5],t[10],a[N];int nxt[N],pre[N];ull f[K*2+5],base[K+5];inline void add(ull w,int on){ int u=w%p; for(int i=head[u];i;i=e[i].nxt){ if(e[i].w==w){ e[i].cnt+=on;return; } } e[++cnt].cnt=1;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt;}inline int ask(ull w){ int u=w%p; for(int i=head[u];i;i=e[i].nxt){ if(e[i].w==w)return e[i].cnt; } return 0;}void merge(int x,int y){ int l=K+1,r=K; memset(f,0,sizeof(f)); for(int i=x;i&&l>1;i=pre[i])f[--l]=a[i]; for(int j=y;j&&r<2*K;j=nxt[j])f[++r]=a[j]; for(int i=l;i<=r;i++)f[i]+=f[i-1]*B; for(int i=l;i<=K;i++){ for(int j=K+1;j<=min(r,i+K-1);j++){ add(f[j]-f[i-1]*base[j-i+1],1); } } nxt[x]=y;pre[y]=x;}void split(int x,int y){ int l=K+1,r=K; memset(f,0,sizeof(f)); for(int i=x;i&&l>1;i=pre[i])f[--l]=a[i]; for(int j=y;j&&r<2*K;j=nxt[j])f[++r]=a[j]; for(int i=l;i<=r;i++)f[i]+=f[i-1]*B; for(int i=l;i<=K;i++){ for(int j=K+1;j<=min(r,i+K-1);j++){ add(f[j]-f[i-1]*base[j-i+1],-1); } } nxt[x]=0;pre[y]=0;}int query(int k){ ll ans=1;ull val=0;int len=strlen(s+1); if(k==1) for(int i=1;i<=len;i++) ans=ans*t[s[i]-'0']%mod; else{ for(int i=1;i<=len;i++){ val=val*B+s[i]-'0'; if(i>k)val-=base[k]*(s[i-k]-'0'); if(i>=k)ans=ans*ask(val)%mod; } } return ans;}int main(){ n=read(),m=read(); base[0]=1; for(int i=1;i<=K;i++)base[i]=base[i-1]*B; for(int i=1;i<=n;i++){ a[i]=read();t[a[i]]++; } for(int i=1;i<=m;i++){ int op=read(); if(op==1){ int x=read(),y=read(); merge(x,y); } if(op==2){ int x=read(); split(x,nxt[x]); } if(op==3){ scanf("%s",s+1); int k=read(); printf("%d\n",query(k)); } } return 0;}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客: +

+++++++++++++++++++++++++++++++++++++++++++

转载于:https://www.cnblogs.com/luyouqi233/p/9050287.html

你可能感兴趣的文章
protocol buffers的编码原理
查看>>
行为型设计模式之命令模式(Command)
查看>>
减少死锁的几个常用方法
查看>>
HDFS 核心原理
查看>>
正确配置jstl的maven依赖,jar包冲突的问题终于解决啦
查看>>
登录内网账号后,连接不上内网网址
查看>>
安装 MariaDB
查看>>
java 为啥变量名前要加个m?
查看>>
探索Android中的Parcel机制(上)
查看>>
C#开发微信门户及应用(5)--用户分组信息管理
查看>>
怎样实现前端裁剪上传图片功能
查看>>
ffmpeg+SDL2实现的视频播放器「退出、暂停、播放」
查看>>
2011/7/3 第二次评审
查看>>
tar解压
查看>>
inheritprototype原型继承封装及综合继承最简实例
查看>>
【磁耦隔离接口转换器】系列产品选型指南
查看>>
Apriori 关联算法学习
查看>>
MVPArms官方首发一键生成组件化,体验纯傻瓜式组件化开发
查看>>
Log4j_学习_00_资源帖
查看>>
制作iso镜像U盘自动化安装linux系统
查看>>