树状数组专辑
树状数组介绍: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
浙公网安备 33010602011771号