• 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 }
  • 相关阅读:
    整个过程
    iframe 重新加载闪过白块问题
    C# 获得两日期之间所有月份(包括跨年)
    新手是个框,啥都往里装!---谨以此文致歉博友和自己的无知
    C# 和Java的foreach的不同用法
    终于鼓起勇气,辞掉了第一份工作
    Java Junit4测试功能
    自学Android的第一个小程序(小布局、button点击事件、toast弹出)
    JS--Div中数据滚动到最后一条重新从头开始滚动
    RelativeLayout与LinearLayout的区别
  • 原文地址:https://www.cnblogs.com/WHLdbk/p/6426579.html
Copyright © 2020-2023  润新知