ACM数据结构-树状数组
Posted TQCAI
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM数据结构-树状数组相关的知识,希望对你有一定的参考价值。
模板:
int n; int tree[LEN]; int lowbit(int x){ return x&-x; } void update(int i,int d){//index,delta while(i<=n){ tree[i]+=d; i+=lowbit(i); } } int getsum(int i){ int ans=0; while(i>0){ ans+=tree[i]; i-=lowbit(i); } return ans; }
示意图:
大佬代码:
//树状数组 #include<iostream> #include<string.h> #include<algorithm> using namespace std; #define MAX 500010 int c[MAX]; int aa[MAX]; int n; typedef struct nano{ int val; int order; }node; node in[MAX]; int lowbit(int x) { return x&(-x); } void update(int x,int val) { while(x<=n){ c[x]+=val; x+=lowbit(x); } } int sum(int x) { int s=0; while(x>=1) { s+=c[x]; x-=lowbit(x); } return s;//一开始竟然忘记写了这个语句,还以为树状数组写错了呢 } bool cmp(node a,node b){ return a.val<b.val; } int main(int argc, char *argv[]) { //freopen("2299.in", "r", stdin); while(scanf("%d",&n)==1&&n){ for(int i=1;i<=n;++i) { scanf("%d",&in[i].val); in[i].order=i; } sort(in+1,in+n+1,cmp); for(int i=1;i<=n;++i) aa[in[i].order]=i;//离散化到小范围来 memset(c,0,sizeof(c)); long long ans=0; for(int i=1;i<=n;++i) { update(aa[i], 1); ans+=(i-sum(aa[i])); } printf("%lld\\n",ans); } return 0; }
大佬代码理解:
首先用结构体node:{val,order} 来存输入信息,用sort(in+1,in+n+1,cmp); 来根据val值进行排序,通过代码
for(int i=1;i<=n;++i) aa[in[i].order]=i;
构造数组aa,aa表示第i个数排第aa[i]位。(代码理解:i表示原本的索引,in[i].order表示排序后的索引)
逆序数计算:
for(int i=1;i<=n;++i) { update(aa[i], 1); ans+=(i-sum(aa[i])); }
ans增量: 索引i之前比他大的数。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <map> #include <vector> #include <queue> #include <cstring> #include <string> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; #define MM(a,b) memset(a,b,sizeof(a)); #define inf 0x7f7f7f7f #define FOR(i,n) for(int i=1;i<=n;i++) #define CT continue; #define PF printf #define SC scanf const int mod=1000000007; const int N=1e6+100; int n,m,c[N],pre[N],sum[N],a[N],ans[N]; struct node{ int l,r,pos; }ne[N]; int lowbit(int i) { return i&(-i); } void add(int p,int u) { while(p<=n) { c[p]^=u; p+=lowbit(p); } } int query(int u) { int res=0; while(u>=1) { res^=c[u]; u-=lowbit(u); } return res; } bool cmp(node a,node b) { return a.r<b.r; } map<int,int> mp; int main() { while(~scanf("%d",&n)) { MM(sum,0);MM(pre,0);MM(c,0); mp.clear(); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum[i]=sum[i-1]^a[i]; if(mp[a[i]]) pre[i]=mp[a[i]]; mp[a[i]]=i; } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&ne[i].l,&ne[i].r); ne[i].pos=i; } sort(ne+1,ne+m+1,cmp); int i=1; for(int k=1;k<=m;k++) { for(;i<=ne[k].r;i++) { if(pre[i]) add(pre[i],a[i]); add(i,a[i]); } ans[ne[k].pos]=(query(ne[k].r)^query(ne[k].l-1)^sum[ne[k].r]^sum[ne[k].l-1]); } for(int i=1;i<=m;i++) printf("%d\\n",ans[i]); } return 0; }
3.模板编写训练1:P3368 【模板】树状数组 1
代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 500010 #define MAX 1<<30 #define V vector<int> #define ll long long using namespace std; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<=\'0\'||ch>\'9\'){if(ch==\'-\')w=-1;ch=getchar();} while(ch>=\'0\'&&ch<=\'9\') s=s*10+ch-\'0\',ch=getchar(); return s*w; } inline ll max(ll a,ll b){ return a>b?a:b; } ll N; ll tree[LEN]; int lowbit(int x){ return -x&x; } ll getsum(int p){ ll sum=0; while(p>0){ sum+=tree[p]; p-=lowbit(p); } return sum; } void update(int p,ll v){ while(p<=N){ tree[p]+=v; p+=lowbit(p); } } int main(){ // freopen("D:\\\\CbWorkspace\\\\ACM数据结构\\\\树状数组\\\\模板1.txt","r",stdin); int m,i,t,op; int a,b; scanf("%d%d",&N,&m); for(i=1;i<=N;i++){ I("%d",&t); update(i,t); } for(i=1;i<=m;i++){ I("%d%d%d",&op,&a,&b); switch(op){ case 1: update(a,b); break; case 2: printf("%lld\\n",getsum(b)-getsum(a-1)); break; } } return 0; }
4.模板编写训练1:P3368 【模板】树状数组 2
代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 500010 #define MAX 1<<30 #define V vector<int> #define ll long long using namespace std; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<=\'0\'||ch>\'9\'){if(ch==\'-\')w=-1;ch=getchar();} while(ch>=\'0\'&&ch<=\'9\') s=s*10+ch-\'0\',ch=getchar(); return s*w; } inline ll max(ll a,ll b){ return a>b?a:b; } ll N; ll tree[LEN]; int lowbit(int x){ return -x&x; } ll getsum(int p){ ll sum=0; while(p>0){ sum+=tree[p]; p-=lowbit(p); } return sum; } void update(int p,ll v){ while(p<=N){ tree[p]+=v; p+=lowbit(p); } } int main(){ // freopen("D:\\\\CbWorkspace\\\\ACM数据结构\\\\树状数组\\\\模板2.txt","r",stdin); int m,i,t,op,pre=0; int a,b,c; scanf("%d%d",&N,&m); for(i=1;i<=N;i++){ I("%d",&t); update(i,t-pre); pre=t; } for(i=1;i<=m;i++){ I("%d",&op); switch(op){ case 1: I("%d%d%d",&a,&b,&c); update(a,c); update(b+1,-c); break; case 2: I("%d",&a); printf("%lld\\n",getsum(a)); break; } } return 0; }
注:使用差分数组
以上是关于ACM数据结构-树状数组的主要内容,如果未能解决你的问题,请参考以下文章