树状数组

树状数组:CDOJ1583-曜酱的心意(树状数组心得)

纵饮孤独 提交于 2020-01-05 03:05:53
曜酱的心意 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 131072/131072KB (Java/Others) Description Chika说希望和我一起做学园偶像的时候,我真的很开心。——WatanabeYou 曜是千歌的青梅竹马,但是Aqours成立以后,千歌似乎总是与梨子在一起,而把曜冷落了。为了让千歌知晓自己的心意,曜酱决定做一件大事!她决定把一个给定的1~n的排列{a1,a2,…,an}(1≤ai≤n),且ai各不相同),用最少的交换次数,变换成另一个1~n的排列{b1,b2,…,bn}。并且,每次只交换相邻的两个元素。也许这样做了以后,千歌能更多地注意自己吧。曜这样想。 Input 第一行是一个整数n,第二行是一个长度为n的1~n的排列a,第三行是另一个长度为n的1~n的排列b。 Output 输出一行,一个整数,表示最少的交换次数。 Sample Input 4 2 3 1 4 3 2 1 4 3 3 2 1 1 2 3 Sample Output 1 3 解题心得: 关于树状数组其实弄的不是很懂,没办法看了好久了。反正树状数组用来求区间和很不错,能够用树状数组解决的基本都能够使用线段树解决。等把树状数组理解更深入了再来写博客。 求逆序数的方法有很多,比如归并排序

[HDOJ4325]Flowers(树状数组 离散化)

梦想与她 提交于 2020-01-05 03:04:24
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4325 关于离散化的简介:http://blog.csdn.net/gokou_ruri/article/details/7723378 假如数据太大,无法作为数组下标来保存对应的属性而采取的一种方法。只需要关注相对大小即可。 我们记下所有的时间数据,再排序。通过二分查找快速定位元素的位置,然后在线段树或者树状数组上仅仅更新这个映射过后的下标位置。因为不需要从线段树或树状数组上直接获取数据(单纯的线段树或树状数组本身是没有意义的,需要搭配相应的数据操作才可以使其称之为线段树或树状数组),也就是说我们更新和查询都是要通过这样一次定位。这样可以解决空间不足的问题。排序后要去重,否则更新到时候可能会更新两次。 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include

树状数组区间修改加区间查询

旧时模样 提交于 2019-12-31 11:14:08
其实之前在 K大数查询 中就已经用到了,只是一直没有说明 所以今天就来补个欠账。 感觉单点修改、区间查询和区间修改、单点查询没什么必要讲,这里就只讲区间修改、区间查询(其实也不难)。 设原数组第 \(i\) 位的值为 \(a_i\) , \(d_i=a_i-a_{i-1}\) ,则有(这里认为 \(a_0=0\) ): \[a_x=\sum_{i=1}^x d_i\] 所以有: \[\sum_{i=1}^x a_i= \sum_{i=1}^x \sum_{j=1}^i d_j =\sum_{i=1}^x(x-i+1)d_i\] 于是我们得到了: \[\sum_{i=1}^x a_i=(x+1)\sum_{i=1}^x d_i-\sum_{i=1}^x d_i \times i\] 于是我们把原数组差分后维护两个树状数组,一个维护 \(d_i\) ,一个维护 \(d_i \times i\) 。 这样区间求和时可以在两个树状数组中查询得到前缀和,区间修改时就是差分数组的修改,每次修改两个点即可。 具体代码如下: void add(int x,int y){for(int i=x;i<=n;i+=i&(-i)) c1[i]+=y,c2[i]+=(long long)x*y;}//给差分数组中的位置x加上y long long sum(int x){//查询前x项的和 long long

高级树状数组——区间修改区间查询、二维树状数组

▼魔方 西西 提交于 2019-12-31 11:13:54
“高级”数据结构——树状数组! ※本文一切代码未经编译,不保证正确性,如发现问题,欢迎指正! 1. 单点修改 + 区间查询 最简单的树状数组就是这样的: void add(int p, int x){ //给位置p增加x while(p <= n) sum[p] += x, p += p & -p; } int ask(int p){ //求位置p的前缀和 int res = 0; while(p) res += sum[p], p -= p & -p; return res; } int range_ask(int l, int r){ //区间求和 return ask(r) - ask(l - 1); } 2. 区间修改 + 单点查询 通过“差分”(就是记录数组中每个元素与前一个元素的差),可以把这个问题转化为问题1。 查询 设原数组为 \(a[i]\) , 设数组 \(d[i] = a[i] - a[i - 1] (a[0] = 0)\) ,则 \(a[i] = \sum_{j = 1}^{i}d[j]\) ,可以通过求 \(d[i]\) 的前缀和查询。 修改 当给区间 \([l, r]\) 加上x的时候, \(a[l]\) 与前一个元素 \(a[l - 1]\) 的差增加了 \(x\) , \(a[r + 1]\) 与 \(a[r]\) 的差减少了 \(x\) 。根据 \

树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

回眸只為那壹抹淺笑 提交于 2019-12-27 05:09:25
题目链接 题意:   有n个点的一棵树。其中树上有m条已知的链,每条链有一个权值。从中选出任意个不相交的链使得链的权值和最大。 思路:   树形DP。设dp[i]表示i的子树下的最优权值和,sum[i]表示不考虑i点时子树的最优权值和,即 (j是i的儿子),显然dp[i]>=sum[i]。那么问题是考虑i点时dp[i]的值是多少,假设有一条链通过i,且端点a和b都在i的子树里,即LCA(a,b)=i,如果考虑加上这条链的权值,那么a->i, b->i的路上的点v都不能有链经过它们(题目要求链不相交),那么-dp[v],但至少有sum[v],即 ,其中v是某条链上的点。那么怎么快速求出sigma的值呢,想到树状数组维护前缀和。那么怎么遍历呢,用DFS序遍历,思想和“ 粮食分配 ”一样,在L[v]上修改,在R[v]上恢复。 #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; const int D = 20; struct Chain { int u, v, w; }; vector<Chain> chains[N]; vector<int> edges[N]; int dp[N], sum[N]; int n, m; int tim; void init() { for (int i=1; i<=n

树状数组例题(2019.12.10)

可紊 提交于 2019-12-10 20:16:31
树状数组例题(2019.12.10) A. Jump 题目描述 有n个障碍物排列在一条直线,障碍物高度为a1,a2,a3…an 有m个独立的询问,一个人最高越过高度为Hi的障碍物,那么在[Li,Ri]区间有多少障碍物是他可以越过的 输入 第一行两个整数n和m(1≤n,m≤1e5) 第二行n个整数,a1,a2,a3…an(1≤ai≤1e9) 余下m行,每行三个整数Li,Ri,Hi(1≤Ri,Li≤n)(1≤Hi≤1e9) 输出 对于每个询问输出一个整数,代表这个人能越过的障碍数量 样例输入 3 3 1 3 2 1 3 1 2 3 1 1 2 4 输出 1 0 2 源代码 #include < bits / stdc ++ . h > #define ll long long #define pii pair < int , int > using namespace std ; const int maxn = 1e6 + 7 ; const int mod = 1e9 + 7 ; struct Quer { int l , r , h , id ; //保存询问的位置id bool operator < ( const Quer & a ) const { //h从小到大排序 return h < a . h ; } } quer [ maxn ] ; int b [ maxn ]

luogu1972 HH的项链(树状数组)

偶尔善良 提交于 2019-12-07 11:18:56
无修改、询问区间种类数的问题可以很容易地用树状数组解决 我们先给询问按右端点排序,然后推着做,每次让a[i]++,表示i处新增了一个种类 但是这样会和前面的有重复,我们只要记下每个种类上次在哪里出现过,当这次又出现了,把前面的那次减掉就可以了 每次处理完之后,就可以计算所有右端点为i的区间的答案,就是这个区间右端点的前缀和减去左端点-1的前缀和 1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=5e5+ 10 ,maxm=1e6+ 10 ; 6 7 inline ll rd(){ 8 ll x= 0 ; char c=getchar(); int neg= 1 ; 9 while (c< ' 0 ' ||c> ' 9 ' ){ if (c== ' - ' ) neg=- 1 ;c= getchar();} 10 while (c>= ' 0 ' &&c<= ' 9 ' ) x=x* 10 +c- ' 0 ' ,c= getchar(); 11 return x* neg; 12 } 13 14 int N,M,tr[maxn]; 15 int col[maxn],lst[maxm],ans[maxn];

【LUOGU 1972】HH的项链

给你一囗甜甜゛ 提交于 2019-12-07 11:17:49
1. 题目链接 。给定一个数组,然后m个询问,每组询问[l,r]输出[l,r]这个区间有多少种元素。 2.这个题目的写法很多,可以莫队,可以树状数组/线段树,也可以直接在线主席树。在这里面感觉离线后树状数组是最好写的(当然,主席树我也写不好)。首先是需要离线所有的询问,然后按照区间的右端点排序,然后对于每一个询问tree[j]存的是[1,j]里面所有元素的的种类,然后对于每一组询问,我们从l,遍历到r,看一下这个区间里第i个位置的数字是不是在前边出现过?如果出现过,就把他从前边出现的位置删了。然后把这个地方的值插进树状数组,注意这里的插入树状数组,不是在这个地方插值,而是插入位置,说明这里出现了一个新的数。然后前缀和就是我们想要的答案。 #include<bits/stdc++.h> #pragma warning(disable:4996) using namespace std; const int maxn = 1e6 + 100; int num[maxn], tree[maxn], vis[maxn], ans[maxn], N, Q; struct point { int l, r; int pos; }; point ask[maxn]; bool cmp(point x, point y) { return x.r < y.r; } void add(int n,

PAT1057 Stack(树状数组+倍增)

♀尐吖头ヾ 提交于 2019-12-06 22:34:39
目录 题目大意 题目分析 题目大意 要求维护一个栈,提供压栈、弹栈以及求栈内中位数的操作(当栈内元素 \(n\) 为偶数时,只是求第 \(n/2\) 个元素而非中间两数的平均值)。最多操作100000次,压栈的数字 \(key\) 范围是[1,100000]。 题目分析 前两个操作用 \(stack\) 就好。 求中位数。暴力做法即使用上优先队列也是稳稳的超时。考虑树状数组。 压栈时,将 \(key\) 值对应的位置加1。弹栈减1。 求中位数,可以二分求出 \(sum[1:p]==(n+1)/2\) 最小的 \(p\) ,即为 \(ans\) 。复杂度 \(O(nlog^2n)\) 。 问题已被解决,但是还有进一步优化的空间。 考虑倍增(?)。从高到低枚举 \(ans-1\) 的每一个二进制位,即求最大的 \(p\) 使得 \(sum[1:p]<(n+1)/2\) 。我们知道树状数组 \(tree[k]=\sum_{i=k-lowbit(k)+1}^knum[i]\) ,也就是说如果我们知道 \(\sum_{i=1}^knum[i]=A\) 且 \((1<<j)<lowbit(k)\) ,那么 \(\sum_{i=1}^{k+(1<<j)}=A+tree[k+(1<<j)]\) 。倍增的时候枚举二进制位的时候,恰巧我们也是从大到小枚举的,满足 \(j\) 与 \(k\) 的限制

计划做题清单

混江龙づ霸主 提交于 2019-12-06 15:02:06
洛谷 并查集P3367 递归P1255 动态规划P1164 排序P1138 优先队列P1323 栈P1449 搜索P1219 八皇后 贪心P1223 P1803 线段树与树状数组 P3368 【模板】树状数组2 P3374 【模板】树状数组1 P3372 【模板】线段树1 P3373【模板】线段树2 OPenJudge 二分 网线切割 枚举 鸡兔同笼 与7无关的数 高精度 \(2^N\) 复习 高精度 读入优化 来源: https://www.cnblogs.com/liuziwen0224/p/11991527.html