hdu1556Color the ball线段树区间更新
线段树区间更新更新一段区间,在更新区间的过程中,区间被分成几段,每一段的左右界限刚好是一个节点的tree[node].left和tree[node].right(如果不是继续分,直到是为止)
区间几次更新后,进行查询,查询的过程就可以看成重走了更新的过程,所以第一种代码中ans+=A[k].count;
ans就是最后答案
1 #include"stdio.h"
2 #include"string.h"
3 #include"stdlib.h"
4 struct tree
5 {
6 int x,y,mid;
7 int count;
8 }A[300001];
9
10 void creat(int x,int y,int k)
11 {
12 A[k].x=x;
13 A[k].y=y;
14 int mid=(x+y)/2;
15 A[k].count=0;
16 if(x==y)return ;
17 creat(x,mid,2*k);
18 creat(mid+1,y,2*k+1);
19 }
20
21 void insert(int x,int y,int k)
22 {
23 if(A[k].x==x&&A[k].y==y)
24 {
25 A[k].count++;return;
26 }
27 int mid=(A[k].x+A[k].y)/2;
28 if(x>mid)insert(x,y,2*k+1);
29 else if(y<=mid)insert(x,y,2*k);
30 else
31 {
32 insert(x,mid,2*k);
33 insert(mid+1,y,2*k+1);
34 }
35
36 }
37
38 int ans;
39 void search(int t,int k)
40 {
41 ans+=A[k].count;
42
43 if(A[k].x==A[k].y&&A[k].x==t)return ;
44 int mid=(A[k].x+A[k].y)/2;
45 if(t<=mid)search(t,2*k);
46 else search(t,2*k+1);
47 }
48
49 int main()
50 {
51 int n,i;
52 int a,b;
53 while(scanf("%d",&n)!=-1&&n)
54 {
55 creat(1,n,1);
56 for(i=0;i<n;i++)
57 {
58 scanf("%d%d",&a,&b);
59 insert(a,b,1);
60 }
61 for(i=1;i<n;i++)
62 {
63 ans=0;
64 search(i,1);
65 printf("%d ",ans);
66 }
67 ans=0;
68 search(i,1);
69 printf("%d\n",ans);
70 }
71 return 0;
72 }
在第二种代码中其实思路是一样的,
if ( seg[idx].l == l && seg[idx].l )
{
seg[idx].cnt++;//这个节点被刷了一次,但实际上是要求seg[idx].l到seg[idx].r的区间都刷一次的,l~r就对应了相应的序号的气球
return;
}
for (int i = seg[idx].l; i <= seg[idx].r; i++)
ans[i] += seg[idx].cnt;//所以在这个区间里,相应的气球都刷一次
1 #include <stdio.h>
2 #include <string.h>
3
4 const int MAXN = 100005;
5
6 typedef struct {
7 int cnt;
8 int l;
9 int r;
10 }Node;
11
12 Node seg[3 * MAXN];
13 int ans[MAXN];
14
15 void build(int idx,int l,int r)
16 {
17 seg[idx].l = l;
18 seg[idx].r = r;
19 seg[idx].cnt = 0;
20
21 if ( l == r )
22 return;
23
24 int mid = ( l + r ) >> 1;
25 build(idx << 1, l, mid);
26 build((idx << 1) + 1, mid + 1, r);
27 }
28
29 void color(int idx,int l,int r)
30 {
31 if ( seg[idx].l == l && seg[idx].l )
32 {
33 seg[idx].cnt++;//这个节点被刷了一次,但实际上是要求seg[idx].l到seg[idx].r的区间都刷一次的,l~r就对应了相应的序号的气球
34 return;
35 }
36
37 int mid = ( seg[idx].l + seg[idx].r ) >> 1;
38 if ( r <= mid )
39 color(idx << 1, l, r);
40 else if ( mid + 1 <= l )
41 color((idx << 1 ) + 1, l, r);
42 else
43 {
44 color(idx << 1, l, mid );
45 color((idx << 1 ) + 1, mid + 1, r);
46 }
47 }
48
49 void solve(int idx)
50 {
51 for (int i = seg[idx].l; i <= seg[idx].r; i++)
52 ans[i] += seg[idx].cnt;//所以在这个区间里,相应的气球都刷一次
53
54 if ( seg[idx].l == seg[idx].r )
55 return;
56
57 solve(idx << 1);
58 solve((idx << 1 ) + 1);
59 }
60
61 int main()
62 {
63 // freopen("1.txt","r",stdin);
64
65 int N;
66 while ( scanf("%d",&N) == 1 )
67 {
68 memset(ans, 0, sizeof(ans));
69 memset(seg, 0, sizeof(seg));
70
71 if ( N == 0 )
72 break;
73
74 build(1,1,N);
75 int p,q;
76
77 for (int i = 0; i < N; i++)
78 {
79 scanf("%d%d",&p,&q);
80 color(1,p,q);
81 }
82
83 solve(1);
84
85 for ( i = 1; i <= N; i++)
86 printf("%d%c",ans[i], ( i == N ) ? '\n' : ' ' );
87
88 }
89
90 return 0;
91 }
第三种代码则有些不同,上面两种代码在更新的时候只更新到了满足left==seg[n].left&&right==seg[n].right的节点,并未继续更新下去直到节点。
而第三种代码则更新到了节点,所以查询代码也是直接查询节点。
1 //不更新所有的节点,如果seg[n].v=0说明这一段是混合的,由他的子节点分开表示
2
3 #include<stdio.h>
4 #define MAXN 100005
5 class seg_tree
6 {
7 public:
8 int mid(){return (left+right)/2;};
9 int left,right,v;
10 }seg[3*MAXN];
11 void build(int n,int left,int right)
12 {
13 seg[n].left=left;
14 seg[n].right=right;
15 seg[n].v=0;
16 if(seg[n].left==seg[n].right)return ;
17 build(2*n,left,seg[n].mid());
18 build(2*n+1,seg[n].mid()+1,right);
19 }
20
21 void update(int n,int left,int right)
22 {
23 if(left==seg[n].left&&right==seg[n].right)
24 {
25 seg[n].v++;
26 return ;
27 }
28 if(seg[n].v>0)//向下更新
29 {
30 seg[2*n].v+=seg[n].v;
31 seg[2*n+1].v+=seg[n].v;
32 seg[n].v=0;//代表这个节点往下的一次更新结束
33 }
34 if(right<=seg[n].mid())update(2*n,left,right);
35 else if(left>seg[n].mid())update(2*n+1,left,right);
36 else
37 {
38 update(2*n,left,seg[n].mid());
39 update(2*n+1,seg[n].mid()+1,right);
40 }
41 }
42 int query(int n,int index)
43 {
44 if(seg[n].left==seg[n].right)
45 {
46 return seg[n].v;
47 }
48 if(index<=seg[n].mid())return seg[n].v+query(2*n,index);
49 else return seg[n].v+query(2*n+1,index);
50 }
51
52 int main()
53 {
54 int n,i,x,y;
55 //freopen("a.txt","r",stdin);
56 while(scanf("%d",&n)&&n)
57 {
58 build(1,1,n);
59 for(i=1;i<=n;i++)
60 {
61 scanf("%d%d",&x,&y);
62 update(1,x,y);
63 }
64 printf("%d",query(1,1));
65 for(i=2;i<=n;i++)printf(" %d",query(1,i));printf("\n");
66 }
67 return 0;
68 }