裸的线段树:
#include <cstdio>
struct Node{
int left, right, n;
} arr[400000 + 10];
void build(int l, int r, int step)
{
arr[step].left = l;
arr[step].right = r;
arr[step].n = 0;
if(l == r) return;
build(l, (l + r) >> 1, step << 1);
build(((l + r) >> 1) + 1, r, (step << 1) + 1);
}
void insert(int s, int t, int step)
{
if(s == arr[step].left && t == arr[step].right){
++arr[step].n;
return;
}
if(arr[step].left == arr[step].right) return;
int mid = (arr[step].left + arr[step].right) >> 1;
if(mid >= t) insert(s, t, step << 1);
else if(mid < s) insert(s, t, (step << 1) + 1);
else{
insert(s, mid, step << 1);
insert(mid + 1, t, (step << 1) + 1);
}
}
bool first;
void dfs(int step, int pre)
{
if(arr[step].left == arr[step].right){
if(first){
printf("%d", pre + arr[step].n);
first = false;
}
else printf("% d", pre + arr[step].n);
return;
}
dfs(step << 1, arr[step].n + pre);
dfs((step << 1) + 1, arr[step].n + pre);
}
int main()
{
int n, l, r;
while(scanf("%d", &n), n){
build(1, n, 1);
while(n--){
scanf("%d %d", &l, &r);
insert(l, r, 1);
}
first = true;
dfs(1, 0);
puts("");
}
return 0;
}
刚学习了树状数组的第二种应用:区间更新,点查询
#include <cstdio>
#include <cstring>
int n, c[100001] = {0};//这里c[i]实际上表示对i的前缀区间整体变化了多少
inline int lowbit(int x){
return x&-x;
}
void update(int x, int d)
{
for(; x; x -= lowbit(x)) c[x] += d;
}
int query(int x)
{
int s = 0;
for(; x <= n; x += lowbit(x)) s += c[x];
return s;
}
void updateSegment(int i, int j, int d)
{
update(i-1, -d);
update(j, d);
}
int main()
{
int i, x, y;
while(scanf("%d", &n), n){
memset(c + 1, 0, n << 2);
for(i = 0; i < n; ++i){
scanf("%d %d", &x, &y);
updateSegment(x, y, 1);
}
printf("%d", query(1));
for(i = 2; i <= n; ++i) printf(" %d", query(i));
puts("");
}
}
终于对一维的树状数组有更深的认识了……