树状数组专辑
树状数组介绍:http://kmplayer.javaeye.com/blog/562119
1.pku 2352 stars
一维。
#include <iostream> #include <cstdio> using namespace std; int c[32005]={0}, l[15005]={0}; int lowbit(int n){ return (n & (-n)); } int sum(int n){ int ans=0; while(n){ ans += c[n]; n -= lowbit(n); } return ans; } void update(int n){ while(n<32005){ c[n]++; n += lowbit(n); } } int main(){ // freopen("c:/aaa.txt","r",stdin); int a, b, n, i; scanf("%d", &n); for(i=1; i<=n; ++i){ scanf("%d %d", &a, &b); l[sum(a+1)]++; update(a+1); } for(i=0; i<n; ++i){ printf("%d\n", l[i]); } return 0; }
二维
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef __int64 lld; int hash[1010][1010]; int map[1010][1010]; int lowbit(int n){ return n & (-n); } void update(int x,int y,int v){ int temp; while(x < 1000){ temp = y; while(temp < 1000){ map[x][temp] += v; temp += lowbit(temp); } x += lowbit(x); } } lld sum(int x,int y){ lld ans = 0; int temp; while(x){ temp = y; while(temp){ ans += map[x][temp]; temp -= lowbit(temp); } x -= lowbit(x); } return ans; } int main(){ // freopen("c:/aaa.txt","r",stdin); int T, ca, n, m, k, a, b, i, j; lld ans; scanf("%d", &T); for(ca=1; ca<=T; ++ca){ printf("Test case %d: ", ca); memset(hash, 0, sizeof(hash)); memset(map, 0, sizeof(map)); scanf("%d %d %d", &n, &m, &k); while(k--){ scanf("%d %d", &a, &b); hash[a][m+1-b] = 1; update(a, m+1-b, 1); } ans = 0; for(i=1; i<=n; ++i){ for(j=1; j<=m; ++j){ if(hash[i][j]){ ans += sum(i-1, j-1); } } } printf("%I64d\n", ans); } return 0; }
3.poj 2155 Matrix
对于任意的a<=b,Up(a)与Down(b)的交集只有一个元素。
//楼教主的题呐,二维树状数组 //翻转的技巧很强 #include <iostream> #include <cstdio> #include <cstring> using namespace std; int C[1010][1010]; int n; int lowbit(int x){ return x & (-x); } void down(int x,int y, int v){ int temp; while(x > 0){ temp = y; while(temp > 0){ C[x][temp] += v; temp -= lowbit(temp); } x -= lowbit(x); } } int up(int x,int y){ int ans = 0; int temp; while(x <= n){ temp = y; while(temp <= n){ ans += C[x][temp]; temp += lowbit(temp); } x += lowbit(x); } return ans; } int main(){ // freopen("c:/aaa.txt","r",stdin); int T, m, ca = 0; int x1, y1, x2, y2; char ch[10]; scanf("%d", &T); while(T--){ if(ca++)printf("\n"); memset(C, 0, sizeof(C)); scanf("%d %d", &n, &m); while(m--){ scanf("%s", ch); if(ch[0] == 'C'){ scanf("%d %d %d %d", &x1, &y1, &x2, &y2); down(x2, y2, 1); down(x2, y1-1, -1); down(x1-1, y2, -1); down(x1-1, y1-1, 1); }else { scanf("%d %d", &x1, &y1); printf("%d\n", up(x1, y1)%2); } } } return 0; }
基本二维树状数组
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int C[1030][1030] = {0}; int n; int lowbit(int x){ return x & (-x); } void add(int x, int y, int v){ int temp; while(x <= n){ temp = y; while(temp <= n){ C[x][temp] += v; temp += lowbit(temp); } x += lowbit(x); } } int sum(int x, int y){ int temp; int ans = 0; while(x > 0){ temp = y; while(temp > 0){ ans += C[x][temp]; temp -= lowbit(temp); } x -= lowbit(x); } return ans; } int main(){ // freopen("c:/aaa.txt", "r", stdin); int a, v, ans; int x1, y1, x2, y2; scanf("%d %d", &a, &n); while(scanf("%d", &a)){ if(a == 3) break; if(a == 1){ scanf("%d %d %d", &x1, &y1, &v); add(x1+1, y1+1, v); }else if(a == 2){ scanf("%d %d %d %d", &x1, &y1, &x2, &y2); ans = sum(x2+1,y2+1) - sum(x2+1,y1) - sum(x1,y2+1) + sum(x1,y1); printf("%d\n", ans); } } return 0; }
//加了io外挂,从2360MS飞到250MS,不可思议。。。 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100001; struct Cow{ int s,e,idx; }cow[100010]; int res[100010]; int C[100010]; int total, n; bool cmp(Cow a, Cow b){ return ( (a.s < b.s) || ((a.s == b.s) && (a.e > b.e)) ); } int lowbit(int x){ return x & (-x); } void add(int x){ while(x <= maxn){ C[x] ++; x += lowbit(x); } } int sum(int x){ int ans=0; while(x > 0){ ans += C[x]; x -= lowbit(x); } return ans; } void Read(int &x){ char ch; x = 0; ch = getchar(); while( !(ch >= '0' && ch <= '9') ) ch = getchar(); while( (ch >= '0' && ch <= '9') ){ x = x * 10 + ch - '0'; ch = getchar(); } } void Output(int x){ char ch; if(x/10 >0){ Output(x/10); } ch = (x % 10) + '0'; putchar(ch); } int main(){ // freopen("c:/aaa.txt","r",stdin); int a, b, i, cnt; cow[0].s = cow[0].e = 0; while(scanf("%d", &n), n){ for(i=1; i<=n; ++i){ Read(a); Read(b); cow[i].s = a + 1; cow[i].e = b + 1; cow[i].idx = i; } sort(cow + 1, cow + n + 1, cmp); memset(C, 0, sizeof(C)); cnt = 0; for(i=1; i<=n; ++i){ if( (cow[i].s == cow[i-1].s) && (cow[i].e == cow[i-1].e) ){ add(cow[i].e); res[cow[i].idx] = res[cow[i-1].idx]; }else { res[cow[i].idx] = cnt - sum(cow[i].e - 1); add(cow[i].e); } ++cnt; } Output(res[1]); for(i=2; i<=n; ++i){ putchar(' '); Output(res[i]); } putchar('\n'); } return 0; }
6.poj 3321 Apple Tree
//竟然卡vector,Tle了n次。 //dfs时,把每个边印上时间戳,转换成连续区间求和,然后树状数组 #include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cstring> using namespace std; const int maxn = 100010; struct node{ int v; struct node * next; }num[maxn]; int low[maxn], high[maxn], c[maxn], flag[maxn]; int n, tt; bool mark[maxn]; int lowbit(int x){ return x & (-x); } void add(int x, int v){ while(x <= n){ c[x] += v; x += lowbit(x); } } int sum(int x){ int ans=0; while(x > 0){ ans += c[x]; x -= lowbit(x); } return ans; } void dfs(int x){ node *ndp = num[x].next; tt ++; mark[x] = true; low[x] = tt; while(ndp){ if(!mark[ndp->v]) dfs(ndp->v); ndp = ndp->next; } high[x] = tt; } void Read(int &x){ char ch; x = 0; ch = getchar(); while( !(ch >= '0' && ch <= '9') ) ch = getchar(); while( (ch >= '0' && ch <= '9') ){ x = x * 10 + ch - '0'; ch = getchar(); } } void Output(int x){ char ch; if(x/10 >0){ Output(x/10); } ch = (x % 10) + '0'; putchar(ch); } int main(){ // freopen("c:/aaa.txt", "r", stdin); int a, b, i, m, ans; char ch; node* ndp; scanf("%d", &n); memset(num, 0, sizeof(num)); for(i=1; i<n; ++i){ Read(a); Read(b); ndp = new node; ndp->next = num[a].next; ndp->v = b; num[a].next = ndp; ndp = new node; ndp->next = num[b].next; ndp->v = a; num[b].next = ndp; } tt = 0; memset(mark, false, sizeof(mark)); dfs(1); memset(c, 0, sizeof(0)); for(i=0; i<maxn; ++i){ flag[i] = 1; } Read(m); while(m--){ ch = getchar(); Read(a); if(ch == 'Q'){ ans = high[a] - low[a] + 1 + sum(high[a]) - sum(low[a] - 1); Output(ans); putchar('\n'); }else{ if(flag[a]) add(low[a], -1); else add(low[a], 1); flag[a]^=1; } } return 0; }
7.北邮oj 1257 Jim 和 Tradia的故事II-第K小数
//主要是find()函数 #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 200010; int c[maxn]; int lowbit(int x){ return x & (-x); } void add(int x){ while(x < maxn){ c[x] ++; x += lowbit(x); } } int find(int k){ int cnt = 0, ans = 0; int i; for(i=20; i>=0; --i){ ans += (1<<i); if(ans >= maxn || cnt + c[ans] >= k) ans -= (1<<i); else cnt += c[ans]; } return ans + 1; } int main(){ // freopen("c:/aaa.txt","r",stdin); int T, ca, m, a; char ch[10]; scanf("%d", &T); for(ca=1; ca<=T; ++ca){ printf("Case #%d:\n",ca); memset(c, 0, sizeof(c)); scanf("%d", &m); while(m--){ scanf("%s %d", ch, &a); if(ch[0] == 'A'){ add(a); }else{ printf("%d\n",find(a)); } } } return 0; }
8.poj 1990 MooFest
//两个树状数组 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef __int64 lld; const int maxn = 20010; struct Node{ int v,x; }cow[maxn]; int c1[maxn],c2[maxn]; int n; bool cmp(Node a, Node b){ return a.v < b.v; } int lowbit(int x){ return x & (-x); } void add(int x, int v,int c[]){ while(x < maxn){ c[x] += v; x += lowbit(x); } } lld sum(int x, int c[]){ lld ans = 0; while(x > 0){ ans += c[x]; x -= lowbit(x); } return ans; } int main(){ // freopen("c:/aaa.txt", "r", stdin); int i; int total, small, big; lld totalV, smallV, bigV; lld ans = 0; scanf("%d", &n); for(i=1; i<=n; ++i){ scanf("%d %d", &cow[i].v, &cow[i].x); } sort(cow+1, cow+n+1, cmp); memset(c1, 0, sizeof(c1)); memset(c2, 0, sizeof(c2)); add(cow[1].x, 1, c1); add(cow[1].x, cow[1].x, c2); totalV = cow[1].x; total = 1; for(i=2; i<=n; ++i){ small = sum(cow[i].x-1, c1); smallV = sum(cow[i].x-1, c2); bigV = totalV - smallV; big = total - small; ans += ( (cow[i].x*small-smallV) + (bigV-cow[i].x*big) )*cow[i].v; totalV += cow[i].x; ++total; add(cow[i].x, 1, c1); add(cow[i].x, cow[i].x, c2); } printf("%I64d\n",ans); return 0; }
9.hdoj 1556 Color the ball
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int n; int c[100002]; int lowbit(int x){ return x & (-x); } void down(int x, int v){ while(x > 0){ c[x] += v; x -= lowbit(x); } } int up(int x){ int ans = 0; while(x <= n){ ans += c[x]; x += lowbit(x); } return ans; } int main(){ // freopen("c:/aaa.txt", "r", stdin); int i, a, b; while(scanf("%d", &n), n){ memset(c, 0, sizeof(c)); for(i=0; i<n; ++i){ scanf("%d %d", &a, &b); down(b, 1); down(a-1, -1); } for(i=1; i<=n; ++i){ if(i == 1) printf("%d", up(i)); else printf(" %d", up(i)); } printf("\n"); } return 0; }
10.hdoj 1892 See you~
二维树状数组。不同便是初始化时各个方格里的值为1,所以树状数组数组初始化为c[i][j] = lowbit(i) * lowbit(j);
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int num[1020][1020]; int map[1020][1020]; void Read( int &x ) { char ch; x = 0; ch = getchar(); while( !(ch >= '0' && ch <= '9') ) ch = getchar(); while( ch >= '0' && ch <= '9' ) { x = x * 10 + ch - '0'; ch = getchar(); } } int lowbit(int n){ return n & (-n); } //int max( int a, int b ) { return a > b ? a : b ; } //int min( int a, int b ) { return a < b ? a : b ; } void update(int x,int y,int v){ int temp; while(x <= 1001){ temp = y; while(temp <= 1001){ map[x][temp] += v; temp += lowbit(temp); } x += lowbit(x); } } int sum(int x,int y){ int temp, ans = 0; if( x<=0 || y<=0 ) return 0; while(x>0){ temp = y; while(temp>0){ ans += map[x][temp]; temp -= lowbit(temp); } x -= lowbit(x); } return ans; } void myset( int &a, int &b, int &c, int &d ) { int minx, miny, maxx, maxy; minx = min( a, c ); miny = min( b, d ); maxx = max( a, c ); maxy = max( b, d ); a = minx; c = maxx; b = miny; d = maxy; } int main(){ // freopen("c:/aaa.txt","r",stdin); int T, ca, n, i, j; int a, b, c, d, v, ans; char ch[5]; scanf("%d", &T); for(ca=1; ca<=T; ++ca){ printf("Case %d:\n", ca); for( i=1; i<=1001; ++i ) { for( j=1; j<=1001; ++j ) { num[i][j] = 1; map[i][j] = lowbit(i) * lowbit(j); } } scanf( "%d", &n ); while( n-- ) { scanf( "%s", ch ); if( ch[0] == 'S' ) { Read(a); Read(b); Read(c); Read(d); //scanf( "%d %d %d %d", &a, &b, &c, &d ); a ++; b++; c++; d++; myset( a, b, c, d ); ans = sum( c, d ) + sum( a-1, b-1 ) - sum( c, b-1 ) - sum( a-1, d ); printf( "%d\n", ans ); } else if( ch[0] == 'A' ) { Read(a); Read(b); Read(c); a ++; b++; num[a][b] += c; update( a, b, c ); } else if( ch[0] == 'D' ) { Read(a); Read(b); Read(c); //scanf( "%d %d %d", &a, &b, &c ); a ++; b++; if( num[a][b] < c ) c = num[a][b]; num[a][b] -= c; update( a, b, -c ); } else if( ch[0] == 'M' ) { Read(a); Read(b); Read(c); Read(d); Read(v); //scanf( "%d %d %d %d %d", &a, &b, &c, &d, &v); a ++; b++; c++; d++; if( num[a][b] < v ) v = num[a][b]; num[a][b] -= v; update( a, b, -v ); num[c][d] += v; update( c, d, v ); } } } return 0; }
一些其他的介绍:
http://hi.baidu.com/flabbyan/blog/item/07a466088483b188d0581b01.html
http://hi.baidu.com/flabbyan/blog/item/29cdeb6119f673d58cb10d02.html