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
",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 ) ? '
' : ' ' );
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("
");
66     }
67     return 0;
68 }
原文地址:https://www.cnblogs.com/WHLdbk/p/6426579.html