链接

https://codeforces.com/contest/213/problem/E

题目大意

给出两个排列a、b,长度分别为n、m,你需要计算有多少个x,使

得\(a_1 + x; a_2 + x; a_3 + x、、、 a_n + x\) 是b 的子序列(不连续的那种)。

思路

巧妙啊

暴力直接扫会T

我们构造一个c数组,使得c[b[i]]=i

这样x+1到x+1+n就是一段连续的区间了233

插回去看看他们相对大小是不是和a数组相同

因为不连续所以线段树维护hash值,线段树按照c数组的原路插回去

查询这一段是否hash值相同

؏؏☝ᖗ乛◡乛ᖘ☝؏؏

不知道双进制有没有用

update 19.3.14

写的稍微有点不清楚

因为a数组是个排列,所以[1,n]总的范围是1到n无重复

这样我们拿b数组开刀,c[b[i]]=i就是下标存值,值存下标。

这样你把他们放回去区间长度为n的下标,和a数组下标比较一下相对大小。

看看是否相同就可以判断是否是子串了。

然后[1,m],[2,m+1],[3,m+2]挨着扫就行了。

错误

报错:你数组开小啦

我:ull炸了吗?

代码

#include <iostream>
#include <cstdio>
#define ull unsigned long long
using namespace std;
const int N=2e5+7;
const int mod[2]={233,1000000009};
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,pos[N],a[N],b[N];
ull my_pow[2][N];
namespace seg {
#define ls rt<<1
#define rs rt<<1|1
struct node {
int siz;
ull tot[2];
}e[N<<2];
int cnt;
void pushup(int rt) {
e[rt].siz=e[ls].siz+e[rs].siz;
e[rt].tot[0]=(e[ls].tot[0]*my_pow[0][e[rs].siz+1]+e[rs].tot[0]);
e[rt].tot[1]=(e[ls].tot[1]*my_pow[1][e[rs].siz+1]+e[rs].tot[1]);
}
void update(int l,int r,int id,int k,int rt) {
if(l==r) {
if(k==-1) e[rt].siz=e[rt].tot[0]=e[rt].tot[1]=0;
else e[rt].siz=1,e[rt].tot[0]=e[rt].tot[1]=k;
return;
}
int mid=(l+r)>>1;
if(id<=mid) update(l,mid,id,k,ls);
else update(mid+1,r,id,k,rs);
pushup(rt);
}
}
int main() {
n=read(),m=read();
my_pow[1][1]=my_pow[0][1]=1;
for(int i=2;i<=n+1;++i) {
my_pow[0][i]=my_pow[0][i-1]*mod[0];
my_pow[1][i]=my_pow[1][i-1]*mod[1];
}
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=m;++i) b[i]=read();
ull hash[2]={0,0},tmp[2]={0,0};
for(int i=1;i<=n;++i) {
hash[0]=(hash[0]*mod[0]+a[i]);
hash[1]=(hash[1]*mod[1]+a[i]);
tmp[0]=(tmp[0]*mod[0]+1);
tmp[1]=(tmp[1]*mod[1]+1);
}
for(int i=1;i<=m;++i) pos[b[i]]=i;
int ans=0;
for(int i=1;i<=m;++i) {
if(i>n) seg::update(1,m,pos[i-n],-1,1);
seg::update(1,m,pos[i],i,1);
if(i>=n&&seg::e[1].tot[0]==(tmp[0]*(i-n)+hash[0])&&
seg::e[1].tot[1]==(tmp[1]*(i-n)+hash[1])) ans++;
}
cout<<ans<<"\n";
return 0;
}

cf213E 线段树维护hash的更多相关文章

  1. MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思维+线段树维护hash值

    F - Permutation 思路:对于当前的值x, 只需要知道x + k, x - k这两个值是否出现在其左右两侧,又因为每个值只有一个, 所以可以转换成,x+k, x-k在到x所在位置的时候是否 ...

  2. BZOJ 2124: 等差子序列 线段树维护hash

    2124: 等差子序列 Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一 ...

  3. bzoj 2124 等差子序列 (线段树维护hash)

    2124: 等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 1922  Solved: 714[Submit][Status][Discuss ...

  4. Codeforces Round #321 (Div. 2) E Kefa and Watch (线段树维护Hash)

    E. Kefa and Watch time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  5. BZOJ 2124 线段树维护hash值

    思路: http://blog.csdn.net/wzq_QwQ/article/details/47152909 (代码也是抄的他的) 自己写得垃圾线段树怎么都过不了 隔了两个月 再写 再挂 又隔了 ...

  6. 线段树 + 字符串Hash - Codeforces 580E Kefa and Watch

    Kefa and Watch Problem's Link Mean: 给你一个长度为n的字符串s,有两种操作: 1 L R C : 把s[l,r]全部变为c; 2 L R d : 询问s[l,r]是 ...

  7. cf580E. Kefa and Watch(线段树维护字符串hash)

    题意 $n$个数的序列,$m + k$种操作 1.$l , r, k$把$l - r$赋值为$k$ 2.$l, r, d$询问$l - r$是否有长度为$d$的循环节 Sol 首先有个神仙结论:若询问 ...

  8. CF213E Two Permutations 线段树维护哈希值

    当初竟然看成子串了$qwq$,不过老师的$ppt$也错了$qwq$ 由于子序列一定是的排列,所以考虑插入$1$到$m$到$n-m+1$到$n$; 如何判断呢?可以用哈希$qwq$: 我们用线段树维护哈 ...

  9. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

随机推荐

  1. Apache Storm Installation

    安装的过程参照此处的过程介绍(https://www.tutorialspoint.com/apache_storm/apache_storm_installation.htm) 安装的过程要安装3个 ...

  2. 【转】求职面试-HR会问你什么问题?

    前言 面试是程序员们经常探讨的话题,只要你通过前面的技术面,最后一面必然是HR面试,基本上到了这关你离Offer的距离应该不会太远了,但有的公司的HR是有刷入的权利,如果你并不能很好的应对HR的问题, ...

  3. 增强for循环遍历集合或数组

    遍历:for循环遍历数组或集合:iterator迭代器遍历集合:还有增强for循环(for each)遍历数组或集合: 遍历数组: 遍历集合:

  4. flask 自定义验证器(行内验证器、全局验证器)

    自定义验证器 在WTForms中,验证器是指在定义字段时传入validators参数列表的可调用对象,下面来看下编写自定义验证器. 行内验证器 除了使用WTForms提供的验证器来验证表单字段,我们还 ...

  5. GAN的文献综述

    1.Conditional Generative Adversarial Netwoks Describe GAN: Generative adversarial nets were recently ...

  6. Kotlin基础学习

        Kotlin 和 java 都是一种静态类型的编程语言.表达式的类型在编译期已经确定,编译期能验证对象是否包含想访问方法或是字段,维护正确性与性能的同时保持源代码的简洁       静态类型的 ...

  7. flask框架----flask中的wtforms使用

    一.简单介绍flask中的wtforms WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证. 安装: pip3 install wtforms 二.简单使用wtfo ...

  8. Linux指令之netstat

    查看某个端口的连接数 netstat -nat | grep -iw "8463" | wc -l [Mac&Redhat通用] 查看连接状况 netstat -nat | ...

  9. Vue小案例 之 商品管理------学习过滤器 使用过滤器处理日期的格式

    代码学习过滤器 过滤器介绍:过滤模型数据,在数据显示前做预处理操作: 内置过滤器:在1.x中,Vue提供了内置过滤器,但是在2.x中已经完全废除: 解决办法: (1)使用第三方库来替代1.x中的内置过 ...

  10. go开发工具及安装使用(Liteide)Liteide-centos6.8 安装

    开发工具介绍 LiteIDE https://github.com/visualfc/liteide/blob/master/liteidex/deploy/welcome/zh_CN/readme. ...