树状数组
szsz
野指针*
这个作者很懒,什么都没留下…
展开
-
P6186 冒泡排序(树状数组 + 思维)
1.冒泡排序每一轮的交换次数等于n - x,x是满足以下条件的数的个数:这个数的前面没有比他大的数.我们称这个数在当前一轮冒泡排序不参与交换.2.冒泡排序的交换的总轮数就是逆序对的总数量.3.每一轮交换都会使得每一个数左边比他大的数减少1, 直到为0.4.对于一个数,如果前面有 x 个数比他大, 那么这个数就会在x + 1进行交换.接下来, 我们只要用总的逆序对的数量减去前k轮减掉的逆序对就可以得到第k轮后的逆序对的数量了,我们可以使用树状数组维护差分的前缀和,具体来说,就是:第一个位置..原创 2022-05-17 23:55:10 · 362 阅读 · 0 评论 -
树状数组优化最长上升子序列和最长公共子序列
我们回忆一下用朴素的dp的解法,对于一个数a[i],我们寻找a[1~i - 1]中小于a[i]的数的最长的子序列长度更新.这里,树状数组优化同样利用了这个思路.我们假设为以值i(注意不是下标)结尾的最长上升子序列的长度,并且用树状数组维护f[x]值.由于值域很大,所以我们要先对值域进行离散化.接着,我们从前向后遍历数组a,找到小于a[i]的最大的x对应的f[x]值,并用f[x] + 1更新f[a[i]].代码如下:#include <bits/stdc++.h>using n..原创 2022-05-14 22:30:04 · 574 阅读 · 0 评论 -
AcWing 244. 谜一样的牛(树状数组 + 二分)
key observation:第k头牛前面有A[k]头比它低,那么它的身高H[k]就是数值1~n中第A[k] + 1大的没有在{H[k+1], H[k+2], ..., H[n]}中出现过的数.我们可以建立一个长度为n的01序列b,起初初始化为1.然后从n到1倒序扫描每个A[i],对于每个A[i]执行以下操作.1.查询序列b中第A[i] + 1个1的位置,这个位置号就是第i头奶牛的身高H[i]2.把b[H[i]]减1(从1变成0)我们可以用树状数组进行这样的操作.代码实现如下:...原创 2022-03-19 16:59:47 · 293 阅读 · 0 评论 -
AcWing 243. 一个简单的整数问题2(树状数组的区间增加和区间查询)
在上一道题中,我们用树状数组维护了原序列的差分数组,得到了不同操作对原序列的累计影响:在这道题中,我们需要求出这些累计影响的前缀和,即:我们对这个式子变形一下:为什么能这么变形呢?我们画图解释:这样,我们只要维护两个树状数组(i*b[i])和(b[i])的即可.具体见代码实现:#include <bits/stdc++.h>#define int long longusing namespace std;const int N = 1e5...原创 2022-03-19 13:12:38 · 143 阅读 · 0 评论 -
AcWing 246. 区间最大公约数(线段树 + 树状数组)
一个gcd(最大公约数)的推论:而且,其实就是的差分,记为算法设计:分别另外建立一个差分序列,用线段树和数组维护前缀和.初始化:add(i, a[i] - a[i - 1])build(1, 1, n + 1)1.对于"C l r d"指令,(树状数组)add(l, d), add(r + 1, -d), (线段树)change(l, d), change(r + 1, -d).2.对于"Q l r"指令,res = gcd(sum(l), ask(1, l + 1, r))...原创 2022-03-20 10:53:11 · 293 阅读 · 0 评论 -
AcWing 241. 楼兰图腾(树状数组求逆序对)
树状数组求逆序对是树状数组的一个基本的运用.我们假设当前要求序列a的逆序对1.在序列a的数值范围上建立树状数组,初始化为全02.倒序扫描序列a,对于每个数a[i]:(1)在树状数组中查询前缀和[1, a[i] - 1],累加到答案ans中.(注意,查询前缀和时,查询的应该是[l - 1, r],而不是[l, r], 比如在这里我们要查询的其实是[0, a[i] - 1])(2)执行"单点增加"操作,把位置上的数加1(相当于c[a[i]]++),同时正确维护c的前缀和.这表示数值a[i]又..原创 2022-03-19 11:08:25 · 204 阅读 · 0 评论 -
AcWing 242. 一个简单的整数问题(树状数组的区间增加与单点查询操作)
树状数组的基本用途就是维护序列的前缀和, 仅支持"单点增加"和"区间查询"操作(代码如下)//单点增加void add(int x, int y){ for (; x <= N; x += x & -x) c[x] += y;}//区间查询int ask(int x){ int ans = 0; for (; x; x -= x & -x) ans += c[x]; return ans;}我们可以..原创 2022-03-19 11:38:08 · 329 阅读 · 0 评论