树状数组专辑

树状数组介绍: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;
} 
2.pku 3067 Japan 

二维

#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;
}

4.poj 1195 Mobile phones  

基本二维树状数组

#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;
}
5.pku 2481 Cows
//加了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

posted on 2011-01-09 11:04  CrazyAC  阅读(360)  评论(0编辑  收藏  举报