树状数组

有关树状数组的数组编码

徘徊边缘 提交于 2019-11-30 06:08:52
一个二维树状数组的问题。 POJ1195 mobile phone 我的二维数组是按照题给的一样0,0开始编码,其他的都相同(源代码如下),把题目中x,y=0的情况映射成x,y=-1的情况,直接返回0,结果永远TLE。然后我把它全部改成从1,1开始编码就AC了。 答案是因为,树状数组的定义就是从1开始编码的。记住了啊,好好看书(和PPT)啊。这也是题目中的坑啊 #include <iostream> #include <stdio.h> using namespace std; const int maxs = 1100; int c[maxs][maxs]; int s; inline int lowbit(int x) { return x & (-x); } inline void change(int x, int y, int d) { for (int xi = x; xi < s; xi += lowbit(xi)) { for (int yi = y; yi < s; yi += lowbit(yi)) { c[xi][yi] += d; } } } inline int getsum(int x, int y) { int sum = 0; if (x < 0 || y < 0) return 0; for (int xi = x; xi >= 0; xi -=

HDU1166 树状数组入门

旧街凉风 提交于 2019-11-30 06:07:38
/**/ #include <cstdio> #include <cstring> #include <cmath> #include <cctype> #include <iostream> #include <algorithm> #include <map> #include <set> #include <vector> #include <string> #include <stack> #include <queue> typedef long long LL; typedef unsigned long long ULL; using namespace std; bool Sqrt(LL n) { return (LL)sqrt(n) * sqrt(n) == n; } const double PI = acos(-1.0), ESP = 1e-10; const LL INF = 99999999999999; const int inf = 999999999, N = 5e4 + 24; int T, n, w, a[N], C[N]; char s[6]; int lowbit(int x) { return (x & -x); } void Add(int i, int w) { while(i <= n) { C[i] += w; i +=

关于线段树和树状数组的一些知识集合

我们两清 提交于 2019-11-30 05:48:05
线段树:用于降低时间复杂度的算法 这是昨天大佬讲的一些算法,我自己整理了一些,顺序有点凌乱,下面还有一些网上大佬们的资料,可以当作消遣看一看。 今天也是努力学习的菜鸡啊QAQ 个人觉得线段树这里还是不难理解的,只是我还不会代码实现(哭辽?) 菜鸡要努力啊!冲鸭! 下面是正文部分: *特点: 有根数:根是确定树中一个点作为根 靠近根的为“父” 远离根的为“子”。 二叉树 只有两个分支的树 分为左分支和右分支 有序的 每个节点可以有不同的含义 (例如:可以代表一个区间的和,最大值,最小值等)可以存在标记(标记下放*不太懂) 若节点为(a,b) 左节点(a,(a+b)/2) 右节点((a+b)/2+1,b) 线段树主要处理区间上的问题 每层最多有两个终止节点(*) 标号的概念:即存储每个节点数据的数组下标 *3.标记下放 EX:求Ai-Aj 的和 其中每个点都加n (标记在节点中存储) 树状数组 重要代码实现;(c++) Using namespace std; Void xg(int x) { While(x<=n); { A[x]++; X+=x&(-x);(x累加x的lowbit) } } (以上是自我笔记) 网上资料: 给定区间【L,R】,如何分解成上述给定的区间? 对于给定区间[2,12]要如何分解成上述区间呢? 分解方法一:自下而上合并——利于理解 先考虑树的最下层

树状数组

こ雲淡風輕ζ 提交于 2019-11-30 03:32:39
#include <iostream> #include <cstdio> using namespace std; const int maxn=5e5+10; long long a[maxn],c[maxn]; inline int lowbit(int x) { return x&(-x); } void build(int n) { for(int i=1;i<=n;i++) { for(int j=i;j<=n;j+=lowbit(j)) c[j]+=a[i]; } return ; } void update(int x,int k,int n) { for(;x<=n;x+=lowbit(x))c[x]+=k; } long long query(int x) { long long ans=0; while(x) { ans+=c[x]; x-=lowbit(x); } return ans; } int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } build(n); int op,x,y; while(m--) { scanf("%d %d %d",&op,&x,&y); if(op==1) { update(x,y,n); }

19 徐州网络赛 query //树状数组离线+素数筛

微笑、不失礼 提交于 2019-11-30 02:09:25
query 我没有好好善待树状数组啊,树状数组在考虑离线+区域求和的时候蛮好用 题意: 给一个排列 p p p ,给 q q q 个询问,每次询问 [ l , r ] [l,r] [ l , r ] 里满足 g c d ( i , j ) = = m i n ( i , j ) ( i < j ) gcd(i,j)==min(i,j)(i<j) g c d ( i , j ) = = m i n ( i , j ) ( i < j ) 的 p a i r pair p a i r 的数量。 思路: 将询问离线,从左到右遍历数组 p p p ,遍历到 p [ i ] p[i] p [ i ] ,统计新出现的 p a i r pair p a i r ,左端点加入到树状数组。 然后处理询问右端点为 i i i 的询问。 预处理每一个 p a i r pair p a i r ,不超过 N l o g N NlogN N l o g N 个。 /* Author : Rshs * Data : 2019-09-18-19.28 */ # include <bits/stdc++.h> using namespace std ; # define FI first # define SE second # define LL long long # define MP make_pair

Gym-10071A-Queries(树状数组)

我是研究僧i 提交于 2019-11-29 19:10:17
链接: https://vjudge.net/problem/Gym-100741A 题意: Mathematicians are interesting (sometimes, I would say, even crazy) people. For example, my friend, a mathematician, thinks that it is very fun to play with a sequence of integer numbers. He writes the sequence in a row. If he wants he increases one number of the sequence, sometimes it is more interesting to decrease it (do you know why?..) And he likes to add the numbers in the interval [l;r]. But showing that he is really cool he adds only numbers which are equal some mod (modulo m). Guess what he asked me, when he knew that I am a programmer?

树状数组

帅比萌擦擦* 提交于 2019-11-29 17:44:44
先粘上我入门时看的博客(下面部分摘自该博客): https://www.cnblogs.com/xenny/p/9739600.html 下面是我粘上以供自己复习的点: 树状数组的优点和缺点 修改和查询的复杂度都是O(logN),而且相比线段树系数要少很多,比传统数组要快,而且容易写。 缺点是遇到复杂的区间问题还是不能解决,功能还是有限。 下面是树状数组的结构: 黑色数组代表原来的数组(下面用A[i]代替),红色结构代表我们的树状数组(下面用C[i]代替),发现没有,每个位置只有一个方框,令每个位置存的就是子节点的值的和,则有 C[1] = A[1]; C[2] = A[1] + A[2]; C[3] = A[3]; C[4] = A[1] + A[2] + A[3] + A[4]; C[5] = A[5]; C[6] = A[5] + A[6]; C[7] = A[7]; C[8] = A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8]; 可以发现,这颗树是有规律的 C[i] = A[i - 2 k +1] + A [i - 2 k +2] + ... + A[i]; //k为i的二进制中从最低位到高位连续零的长度 如果我们要找前7项和,那么应该是SUM = C[7] + C[6] + C[4]; 而根据上面的式子,容易的出

Light bulbs (树状数组模板题)

限于喜欢 提交于 2019-11-29 16:54:55
There are N light bulbs indexed from 0 0 to N − 1. Initially, all of them are off. A FLIP operation switches the state of a contiguous subset of bulbs. FLIP(L, R) means to flip all bulbs x such that L ≤ x ≤ R. So for example, FLIP(3, 5) means to flip bulbs 3 , 4 and 5, and FLIP(5, 5) means to flip bulb 5. Given the value of N and a sequence of M flips, count the number of light bulbs that will be on at the end state. InputFile The first line of the input gives the number of test cases, T . T test cases follow. Each test case starts with a line containing two integers N and M, the number of

8.26 树状数组

大憨熊 提交于 2019-11-28 21:39:50
题意 对于一个有两个参数的函数 \(f(l,r)\) 我们定义其值为: 在树状数组中 \(l-1\) 位置减一, \(r\) 位置加一 最后得到的树状数组中不为 \(0\) 的位置的个数 求 \[ \sum_{i=1}^n\sum_{j=i}^nf(i,j) \] \(N \leq 10^{18}\) 答案对 \(10^9+7\) 取模 解法 这题很巧妙 为了方便,我们把 \(f(l,r)\) 重定义为在 \(l\) 处减一, \(r\) 处加一 我们可以发现 \(f(l,r)\) 其实就是 \(l\) 与 \(r\) 的二进制表示中所有的一的个数减去两倍其 \(lcp\) 中一的个数 这个还是很好发现的,参见 \(lowbit\) 的定义 由于 \(N\) 达到了 \(10^{18}\) 考虑按位进行统计 从高位到低位枚举 \(lcp\) ,设当前枚举到 \(i\) , \(n\) 在二进制表示下的长度为 \(len\) 则 \(i...len\) 为当前串的 \(lcp\) 则这种情况下 \(lcp\) 的贡献为 \(lcp\) 中一的个数 如果第 \(i-1\) 位为 \(1\) ,那么为了使 \(lcp\) 保持在 \(i...len\) ,第 \(i-1\) 为一定只能填 \(0\) 由于这一位填 \(0\) ,我们保证了填的数一定小于上界 这样 \(i\)

cf 1208D 树状数组+倍增/线段树

笑着哭i 提交于 2019-11-28 19:19:13
解法一 树状数组: ```math 倒序,对于每个s_{i},找出从1-n中的未被利用且和为s_{i}的前缀和,则p_{i}为这些数中最大的数+1,每次找都后需要及时删去 此处查找使用倍增的方法。 数组数组+倍增,单次操作O(log n) 树状数组+二分,单次操作O(log n*log n) #include <bits/stdc++.h> using namespace std; #define ll long long ll s[200050], c[200050]; ll p[25]; int n, t, h[200050]; void add(int x, int t) { while (x <= n) { c[x] -= t; x += x&-x; } } int main() { p[0] = 1; for (int i = 1; i<22; i++)p[i] = p[i - 1] << 1; scanf("%d",&n); t = log(n) / log(2); for (int i = 1; i <= n; i++) { scanf("%lld",&s[i]); c[i] += i; if (i + (i&-i) <= n)c[i + (i&-i)] += c[i]; } // for(int i=1;i<=n;i++) // cout<<c[i]<<" "; /