显然只能有$hash$来做....

我们需要一个东西来维护$\sum i * seed^{rank[i]}$

很自然地联想到平衡树

如果以序列下标建立一棵平衡树,那么无法处理

因此,可以以权值为下标建立一棵平衡树,把$rank[i]$拆分成若干个$sz[ls] + 1$即可维护

具体而言,记$pos[i]$表示$i$号节点的位置,$sum[i]$表示平衡树中$i$号节点的子树形成的$hash$值

那么,$sum[i] = pos[i] * seed^{sz[ls] + 1} + sum[ls] + sum[rs] * seed^{sz[ls] + 1}$

首先预处理出所有$A$串的$hash$值,存进$map$中

处理时,注意$[1, m]$和$[2, m + 1]$的串在平衡树中的$hash$值会有一个增量的区别

由于元素两两不同,因此可以确定增量为$\sum seed^i$

之后,每次动态地维护$B$串的$hash$值,查询即可

下面的代码由于插入了$-1$,因此更新时略有不同...

复杂度$O(n \log n)$

#include <map>
#include <cstdio>
#include <cstring>
using namespace std; #define ll long long
#define ri register int
#define ull unsigned long long
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)
#define gc getchar
inline int read() {
int p = ; char c = gc();
while(c > '' || c < '') c = gc();
while(c >= '' && c <= '') p = p * + c - '', c = gc();
return p;
} const int sid = ;
const int seed = ; ll val[sid];
map <ull, int> ans;
int n, m, q, rt, id, A[sid], B[sid];
ull pos[sid], sum[sid], wei[sid];
int s[sid][], sz[sid], fa[sid]; inline bool isrc(int o) {
return s[fa[o]][] == o;
} inline void upd(int o) {
int ls = s[o][], rs = s[o][];
sz[o] = sz[ls] + sz[rs] + ;
sum[o] = wei[sz[ls]] * pos[o] + sum[ls] + wei[sz[ls] + ] * sum[rs];
} inline void rotate(int o) {
int f = fa[o], g = fa[f];
int ro = isrc(o), rf = isrc(f);
fa[o] = g; if(g) s[g][rf] = o;
s[f][ro] = s[o][ro ^ ];
fa[f] = o; fa[s[o][ro ^ ]] = f;
s[o][ro ^ ] = f; upd(f); upd(o);
} inline void splay(int o, int tar) {
while(fa[o] != tar) {
int f = fa[o], g = fa[f];
if(g != tar) rotate(isrc(o) == isrc(f) ? f : o);
rotate(o);
}
if(!tar) rt = o;
} inline void insert(ll v, int w) {
int o = rt, f = ;
while(o) f = o, o = s[o][v > val[o]];
o = ++ id;
if(f) s[f][v > val[f]] = o;
fa[o] = f; sz[o] = ; val[o] = v;
pos[o] = w; sum[o] = w;
splay(o, );
} inline void find(ll v) {
int o = rt;
while(s[o][v > val[o]] && val[o] != v)
o = s[o][v > val[o]];
splay(o, );
} inline void erase(int v) {
find(v);
int pre = s[rt][], suf = s[rt][];
while(s[pre][]) pre = s[pre][];
while(s[suf][]) suf = s[suf][];
splay(pre, ); splay(suf, pre);
s[suf][] = ;
if(suf) upd(suf);
if(pre) upd(pre);
} inline void Hash() {
ull exa = ; wei[] = ;
rep(i, , m + ) wei[i] = wei[i - ] * seed;
rep(i, , m) exa += wei[i]; insert(-, ); insert(, );
rep(i, , m) insert(A[i], i);
rep(i, m, n) {
ans[sum[rt] - exa * (i - m)] ++;
if(i == n) break;
erase(A[i - m + ]);
insert(A[i + ], i + );
}
rt = ;
rep(i, , id) {
s[i][] = s[i][] = sz[i] = ;
val[i] = sum[i] = fa[i] = ;
}
id = ;
} int main() {
n = read(); m = read(); q = read();
rep(i, , n) A[i] = read();
Hash();
insert(-, ); insert(, );
rep(i, , m) B[i] = read();
rep(i, , m) insert(B[i], i);
rep(i, , q) {
int x = read(), c = read();
erase(B[x]);
insert(B[x] = c, x);
printf("%d\n", ans[sum[rt]]);
}
return ;
}

luoguP4715 [英语]Z语言 平衡树+hash的更多相关文章

  1. 中文编程语言Z语言开源正式开源!!!

    (Z语言基于.NET环境,源码中有很多高技术的代码,让更多的人知道对大家有会有很好的帮助,请管理员一点要批准放在首页) 本人实现的中文编程语言Z语言现在正式开源,采用LGPL协议. 编译器核心的网址为 ...

  2. 中文编程语言之Z语言初尝试: ZLOGO 4

    原文: https://zhuanlan.zhihu.com/p/31505895. 作者为本人. @TKT2016 开发的Z语言(ZLOGO是它的一个部分)是本人至今看到的唯一一个仍活跃开发的开源且 ...

  3. 2017-11-28 中文编程语言之Z语言初尝试: ZLOGO 4

    "中文编程"知乎专栏原文. 作者为本人. @TKT2016 开发的Z语言(ZLOGO是它的一个部分)是本人至今看到的唯一一个仍活跃开发的开源且比较完整的中文编程语言项目. 它的源码 ...

  4. 除了C语言,C++······竟然还有Z语言?

    只能说自己见识短,头一次听说Z语言.先普及一下吧: Z语言是由牛津大学程序设计研究小组开发的一种形式语言,它是一种以一阶谓词演算为主要理论基础的规约语言,是一种功能性语言.Z语言是将事物的状态和行为用 ...

  5. [Luogu4715]「英语」Z 语言

    luogu description 你有一个长度为\(n\)的串\(A\)和一个长度为\(m\)的串\(B\),字符集大小\(2^{31}\),且同一个串中没有相同的元素. 定义\(B\)串与\(A_ ...

  6. P4715 「英语」Z 语言

    题解: 平衡树维护hash值 为了支持加入删除操作 x*base^y 其中y为他是第k大 同一般的维护方法,我们不用对每个节点维护他的hash值 而是只用记录他的x值(他的位置) 然后通过updata ...

  7. luoguP4036 [JSOI2008]火星人 平衡树+hash

    这个操作十分的复杂 但是可以拿平衡树维护 直接二分答案然后用$hash$值判断即可 复杂度$O(10000 * log^2 n + n \log n)$ #include <cstdio> ...

  8. inno setup 多语言安装

    之前的安装程序默认语言为英文,现在我们需要将它变成中文,由于InnoSetup安装包中默认没有带中文语言文件,我们需要下载一个先: 到http://www.400gb.com/u/758954/123 ...

  9. 学习C++语言的50条忠告

    50条忠告:(其中有几条觉得写的不够贴切,所以删了,发了余下的部分) 1.把C++当成一门新的语言学习: 2.看<Thinking In C++>,不要看<C++变成死相>: ...

随机推荐

  1. JS模块规范

    ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们采用的是CommonJS规范,使用require引入模块,使 ...

  2. util.promisify 的那些事儿

    util.promisify是在node.js 8.x版本中新增的一个工具,用于将老式的Error first callback转换为Promise对象,让老项目改造变得更为轻松. 在官方推出这个工具 ...

  3. windows 批处理文件调用exe

    @echo offstart "" "C:\Users\Administrator\Desktop\testtaotao\Debug\testtaotao.exe&quo ...

  4. accept系统调用

    /* * For accept, we attempt to create a new socket, set up the link * with the client, wake up the c ...

  5. ubuntu git 简单入门【转】

    转自:http://blog.chinaunix.net/uid-20718384-id-3334859.html 1. 安装 sudo apt-get install git-core 2.  初始 ...

  6. aarch64_a1

    AGReader-1.2-16.fc26.aarch64.rpm 2017-02-14 07:01 50K fedora Mirroring Project ATpy-0.9.7-11.fc26.no ...

  7. 十七、springboot配置FastJson为Spring Boot默认JSON解析框架

    前提 springboot默认自带json解析框架,默认使用jackson,如果使用fastjson,可以按照下列方式配置使用 1.引入fastjson依赖库: maven: <dependen ...

  8. JAVA随笔(二)

    在函数传参时,double传给int是不行的,反过来可以.参数只能传值.当参数是字符串时,传递的只是串值:但对于数组来说,传递的是管理权,也就是指针 对象变量是对象管理者. cast转型:基本类型与对 ...

  9. C实现线程池

    简介:这里使用linux下的互斥锁和条件变量实现了一个线程池.代码由一个未知作者完成,第二任作者补充优化. 本人仅仅是做了一些注释工作. 代码如下: /*! .h */ #include <st ...

  10. Ubuntu 搭建docker registry 私有仓库

    一.为什么要搭建 docker 私有仓库 原因有几个: 项目需要,不希望将项目放到 docker hub 上. 环境需求,考虑网络.效率的问题,希望在私有服务器上建立自用的仓库,提高便利性和访问速度. ...