树状数组

[AC自动机][树状数组]luogu P2414 阿狸的打字机

浪子不回头ぞ 提交于 2019-11-26 15:45:37
https://www.luogu.org/problem/P2414 分析 容易发现询问串A属于串B多少次就是问访问串B时,跳完每个点的fail链,到达串A末尾的次数 可以发现如果把fail树建出来,就相当于每到达一个点,就往fail树里面权值+1,离开时-1,当到达串B末尾时,询问串A末尾在fail树中子树的权值和 用DFS序和树状数组可以轻松解决 #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> #define lowbit(x) x&-x using namespace std; const int N=2e5+10; struct Graph { int v,nx; }g[N]; int gcnt,list[N]; int fail[N],t[N][26],cnt,v[N]; struct Query { int x,y,id; }q[N]; int m,len,tme,p; int l[N],r[N],end[N],ans[N],f[N]; char c[N]; void Add(int u,int v) { g[++gcnt]=(Graph){v,list[u]};list[u]=gcnt; } bool CMP(Query a

ZOJ 2112 Dynamic Rankings(树状数组+主席树)

寵の児 提交于 2019-11-26 14:57:33
The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same. Your task is to write a program for this computer, which - Reads N numbers from the input (1 <= N <

树状数组-luogu-P1972-HH的项链

亡梦爱人 提交于 2019-11-26 06:12:49
题目大意 给定一个长度为n的数列,给出m个询问,每个询问的内容为:统计指定 闭区间 [l,r]内不同元素的个数。 1<n,m<=2e6 问题分析 问题规模巨大,暴力枚举显然会超时。 因为操作中 只有询问没有更新 ,所以可以使用 离线算法 。 经验判断。。。这一道可以用 树状数组 解决的问题,但分析如下: 这里我们需要求得 任意区间 内的不同元素个数,不同区间经常会存在在不同程度的 重叠 , 直接枚举显然会做很多重复计算 。我们知道 前缀和 是一种很棒的思想,它可以让我们在O(1)的时间复杂度内 快速求得区间和 。我们便会思考是否能利用 前缀和 这种思想来解决这一问题。 当使用前缀和时,对于查询区间[l.r],我们希望能以如下方式得到答案: ans=sum[r]-sum[l-1] ,可见对应与前缀和的原始被计数的数组a[]来说,a[i]应该存放的是“i处为不同于之前元素的个数”,也就是说, 如果i处的元素是未出现的(不重复的),则a[i]=1;如果i处的元素是重复的,则a[i]=0 。但 重复与否与查询区间有关 ,重复指的是在查询区间内发生重复, 区间外不影响对重复的统计 。这就意味着a[i]的值 不应该简单的一次确定好 ,而是应该随着查询区间的变化来做出调整;a[i]的变化也势必会引起sum[i]…sum[n-1]的变化,所以sum[i]也 不会简单的一次确定好

多段树状数组

故事扮演 提交于 2019-11-26 02:53:52
固定总长的多棵树状数组 概述 有时候,我们需要很多棵树状数组,每棵尺寸的值域都很大,但总长是固定的并且不太大。 此时我们可以将所有树状数组顺序放在一个数组上面,将询问离线后给每棵树状数组标一个起点和尺寸,每次从起点开始按照正常的二进制位做即可。 一般形式 先直接给出伪代码 inline void update(int *树状数组起点,int 树状数组尺寸,int 询问位置,int 更新值){ while(下标<=尺寸){ 进行更新, 下标加上lowbit } } inline void update(int *树状数组起点,int 树状数组尺寸,int 询问位置){ while(下标不为零){ 统计贡献 下标减去lowbit } } 调用 update(树状数组+起点[i],尺寸[i],位置,值) printf(query(树状数组+起点[i],尺寸[i],位置)) 可以看到,和普通的树状数组几乎一样,因为拆分后的部分数组符合树状数组所有的性质。 例题 P3960 列队 这道题抽象后需要维护 \(N\) 行中的 \(Q\) 个区间,需要构造 \(N\) 个数组支持二分查找每一个区间,这时候我们可以将区间按照行数编号排序,建一棵长度为 \(Q\) 的树状数组,然后用上面的方法对于每行建立树状数组,复杂的二分查找查找也可以进行。 inline void update(LL *ar