树状数组

luogu_P3374 【模板】树状数组 1

烈酒焚心 提交于 2019-12-03 07:12:59
操作:区间和询问,单点增加 #include<iostream> #include<cstdio> #define ri register int #define u int namespace opt { inline u in() { u x(0),f(1); char s(getchar()); while(s<'0'||s>'9') { if(s=='-') f=-1; s=getchar(); } while(s>='0'&&s<='9') { x=(x<<1)+(x<<3)+s-'0'; s=getchar(); } return x*f; } } using opt::in; #define NN 500005 namespace mainstay { u N,K; u c[NN]; inline u ask(const u &x){ u _re(0); for(ri i(x);i;i-=i&-i) _re+=c[i]; return _re; } inline void add(const u &x,const u &y){ for(ri i(x);i<=N;i+=i&-i) c[i]+=y; } inline void solve() { N=in(),K=in(); for(ri i(1);i<=N;++i){ u _a(in()); add(i,_a); }

HDU4638 Group (树状数组+离线处理)

匿名 (未验证) 提交于 2019-12-03 00:40:02
在网上看了好多大神的博客,反正自己是绝对想不到怎么做的,好不容易感觉自己迷迷糊糊懂了个大概,就先记下来,免得以后忘记。有的地方思路很勉强甚至是错的,欢迎大家指教纠正。 题意:给你一个1~n的排列序列,m次查询,每次给出一个区间,求这个区间内使每个分组里面的数字都是连续的最小的分组方法。(题目链接: 点击打开原题链接 ) 题解:因为求的是区间内的连续数字的分组,那么对于当前要查询的区间来说,它前面的数字就是无效的,所以我们可以将所有要查询的区间储存起来然后排序,从第一个区间开始把左边的不会用到的数“删除”,这里说的“删除”不是将这个数从数列里面去掉,而是指把它自身对最终答案的贡献变为0 。怎么做到这一点呢? 首先我们要初始化每个位置的数对当前整个序列来说的分组贡献(在树状数组上操作,方便单点更新和区间查询): (1)当一个数单独出现而它左右的数字并没有出现的时候,这个数只能单独被分为一个区间,那它对分组数量的贡献就为1; (2)当一个数出现时,它的前面或者后面的数字已经出现了,那么这个数就能和它组成一个区间,所以不需要新增分组,它对分组数量的贡献为0; (3)当一个数出现前它的前后的数字都已经出现了,那么这个数就能将前后两个数连起来使两个区间变成一个区间(一个数的前后两个数原本是不能连在一起的),那么区间数就会减少,所以它对分组数的贡献为-1; 初始化以后

#树状数组,二分#poj 2182 Lost Cows

匿名 (未验证) 提交于 2019-12-03 00:32:02
排在奶牛前面的奶牛数量实际上比那头奶牛的品牌要小,求奶牛的排序。 二分+树状数组,倒推,二分求出排列,用树状数组求品牌的数量。 #include <cstdio> using namespace std ; int n,a[ 8001 ],c[ 8001 ]; void add( int x){ while (x<=n) c[x]++,x+=(x&(-x));} int answ( int x){ int ans= 0 ; while (x){ ans+=c[x]; x-=(x&(-x)); } return ans; } int ef( int x){ int l= 1 ,r=n; while (l<r){ int mid=(l+r)>> 1 ; int t=answ(mid); if (mid- 1 -t>=x) r=mid; else l=mid+ 1 ; } return l; } int main(){ scanf ( "%d" ,&n); for ( int i= 1 ;i<n;i++) scanf ( "%d" ,&a[i]); for ( int i=n- 1 ;i>= 0 ;i--){ int x=ef(a[i]); a[i]=x; add(x); } for ( int i= 0 ;i<n;i++) printf ( "%d\n" ,a[i]); return

Just h-index+莫队+二分+树状数组

匿名 (未验证) 提交于 2019-12-03 00:22:01
Just h -index Problem Description The h -index of an author is the largest h where he has at least h papers with citations not less than h . Bobo has published n papers with citations a 1 , a 2 , … , a n respectively. One day, he raises q questions. The i -th question is described by two integers l i and r i , asking the h -index of Bobo if has *only* published papers with citations a l i , a l i + 1 , … , a r i . Input The input consists of several test cases and is terminated by end-of-file. The first line of each test case contains two integers n and q . The second line contains n integers

LIS 树状数组优化

匿名 (未验证) 提交于 2019-12-03 00:14:01
lis 众所周知 即最长上升子序列 可以用dp求解 复杂度O(n^2) 我们考虑优化 用树状数组(或者线段树) 树状数组维护区间最大值 (省去原始O(n^2)算法中的查找) 这样还能求出以i结尾的lis 二分只能求出当前序列的lis (许多题里要求lis个数什么的qwq 总之比二分方便 除了码量长 ) 还有一个小点就是可能会用到离散化( 传送门 ) 具体实现看代码 #include < bits / stdc ++. h > using namespace std ; int a [ mxn ], b [ mxn ], n , sz , ans ; int dp [ mxn ], f [ mxn ]; int lowbit ( int x ){ return x &(- x ); } int motify ( int x , int w ){ for (; x <= m ; x += lowbit ( x )){ f [ x ]= max ( f [ x ], w ); } } int get ( int x ){ int temp = 0 ; for (; x ; x -= lowbit ( x )){ temp = max ( temp , f [ x ]); } return temp ; } int main (){ cin >> n ; for ( int i = 1 ;

POJ2182 Lost Cows 树状数组,二分

匿名 (未验证) 提交于 2019-12-03 00:13:02
题意:给n个奶头身高从1到n,现在奶牛排成一列,给n-1个数字,为第二号奶牛到第n号奶牛前面比它矮的奶牛个数。 求这个序列每个奶牛的身高。 思路:从最后一个奶牛开始判断,因为最后一个奶牛是和前面所有奶牛做比较的,我们可以根据比它矮的奶牛个数确定它的身高,如果前面有3个比它矮那么它身高绝对为4,而继续判断前一个奶头身高时,要把这个奶牛剔除考虑, 所以我们想到可以维护一个长度为n的01序列,为1表示奶牛还在,奶牛从后往前遍历,设比它矮的有k个,每次找奶牛身高,就是找存在的奶牛中k+1的位置,也就是前缀和为k+1的位置,每次可以二分来判断位置,0(1)删除一个奶牛 #include < bits / stdc ++. h > using namespace std ; const int maxn = 8e3 + 10 ; #define ll long long int a [ maxn ]; int c [ maxn ]; int n ; int ans [ maxn ]; int ask ( int x ) { int ans = 0 ; for (; x ; x -= x &- x ) ans += c [ x ]; return ans ; } void add ( int x , int y ) { for (; x <= n ; x += x &- x ) c [ x ]+

【模板】3 树状数组1(单点修改区间查询)

匿名 (未验证) 提交于 2019-12-02 23:59:01
#include<iostream> #include<cstdio> using namespace std; int pd,c[500001],a[500001],x,y,k,n,m; int lowbit(int xx) { return xx&-xx; } void update(int xx,int yy) { while(xx<=n) { c[xx]+=yy; xx+=lowbit(xx); } } int getsum(int xx) { int sum=0; while(xx>0) { sum+=c[xx]; xx-=lowbit(xx); } return sum; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) { cin>>a[i]; update(i,a[i]); } for(int i=1;i<=m;i++) { cin>>pd; if(pd==1) { cin>>x>>k; update(x,k); } if(pd==2) { cin>>x>>y; cout<<getsum(y)-getsum(x-1)<<endl; } } return 0; }                                    2019-09-09 By十四日的夏 来源:博客园 作者: 十四日的夏 链接:https:

树状数组模板

匿名 (未验证) 提交于 2019-12-02 23:55:01
树状数组 1 单点修改,区间查询 这个没啥好讲的,修改加查询即可,查询时利用前缀和相减即可。 代码 #include<bits/stdc++.h> using namespace std; const int maxn=1000010; int n,q,u,v,k,a[maxn]; long long c[maxn]; int lowbit(int x){ return x&(-x); } void add(int x,long long y){ for(;x<=n;x+=lowbit(x)) c[x]+=y; } long long ask(int x){ long long ans=0; for(;x;x-=lowbit(x)) ans+=c[x]; return ans; } int main(){ scanf("%d %d",&n,&q); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); add(i,a[i]); } while(q--){ scanf("%d %d %d",&k,&u,&v); if(k==1){ add(u,v); } else{ printf("%lld\n",(ask(v)-ask(u-1))); } } return 0; } 树状数组 2 区间修改,单点查询 这道题还是比较简单的,树状数组仅支持“单点修改

树状数组(区间修改,区间查询 )

匿名 (未验证) 提交于 2019-12-02 23:49:02
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 long long n,m; 6 long long a[500009]; 7 long long c[500009],d[500009]; 8 long long lowbit(long long x) 9 { 10 return (x&(-x)); 11 } 12 void change(long long *e,long long x,long long k) 13 { 14 for(int i=x;i<=n;i+=lowbit(i)) 15 { 16 e[i]+=k; 17 } 18 } 19 long long query(long long *e,long long x) 20 { 21 long long sum=0; 22 for(int i=x;i>=1;i-=lowbit(i)) 23 { 24 sum+=e[i]; 25 } 26 return sum; 27 } 28 int main() 29 { 30 cin>>n>>m; 31 for(int i=1;i<=n;i++) 32 { 33 cin>>a[i]; 34 change(c,i,a[i]-a[i-1]); 35 change(d,i,(long long)(i-1

2019.7.15-7.20暑假集训总结

匿名 (未验证) 提交于 2019-12-02 23:49:02
// 7.18前三天的等我周日再继续复习总结orz _(:з」∠)_每一天都是充实的欧 7.15:差分与前缀和 7.16: 倍增与ST表 7.17:并查集进阶 7.18:树状数组与线段树 树状数组: 1 .引入lowbit(x) int lowbit(int i) { } -11=(0100+1)=0101 &1011 树状数组 c[x],比如c[4], 4的二进制是(100),100刚好是3位数, 所以这个树状数组到c[4]为止 高度 是3。 除了树根,c[x]的 父节点为 c[x+lowbit(x)] 能用树状数组尽量用树状数组,快,省空间。( 一般用来单点更新,区间求和,维护最大值二不能维护最小值。 但是 求区间最大值的时候复杂度比较高 容易TLE,这个时候还是需要用到 线段树 ) “细细观察二进制 树状数组追其根本就是二进制的应用” 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int M =100000+100; 4 int n,t; 5 int a[M],C[M]; 6 int lowbit(int x) 7 { 8 return x&(-x); 9 } 10 int sum(int x) 11 { 12 int ret=0; 13 while(x) 14 { 15 ret+=C[x]; 16 x-