zoukankan      html  css  js  c++  java
  • poj pku 2528 线段树的基础应用


    郁闷了一上午的题目,一直都是WA,找了老半天错,想了很多测试数据还是WA。就连骑单车回家的路上还在想这题。悲剧呀。。。
    做完这个题目才明白线段树不同于其他算法,它只是一种思想,在实际应用中是要根据题意灵活去运用才行。
    http://162.105.81.212/JudgeOnline/problem?id=2528
    题目大意很简单,给点了区间着色,最后能看到几个区间的颜色。
    此题显然是线段树的题目,不过区间有10000000那么大,冒冒失失的就去建树,然后插入是不行的。如果不离散化的话在建树与插入的时候多了太多的没必要的搜索和没必要的内存空间。
    假设给定的区间是[1,3],[6,1000],我们可以如下离散
    离散前坐标:1 3 6 1000
    离散后坐标:1 2 3 4
    于是我们就减少了没必要的搜索过程和内存空间。有个建树时的小技巧,因为我建树的每个节点是开区间到闭区间,即[a,b)。于是在读入数据的时候我就可以把b的值加一,这样就很好的处理了题目中可能出现的[a,a]相等值的区间(也就是对一个点的处理)。
    在统计覆盖的时候我们可以采用倒覆盖的方式去统计。
    可无论我怎么交,一直都是返回WA。直到我测试的时候发现了这组数据:
    5
    12 13
    1 12
    1 1
    2 13
    1 3
    返回的正解应该是2,而我的是3。检查程序才发现在插入的时候如果结点左右子树都已覆盖那么它也应该是覆盖了的。举例来说如果区间[1,2),[2,4)先覆盖了,那么根节点区间[1,4)它也应该是覆盖了的。处理后就返回的是AC。。

    #include <iostream>
    #include <string>
    using namespace std;

    const int MAX_N = 20010;

    struct In
    {     
           int left;
           int right;
    }str[8*MAX_N];

    struct Node
    {
           int left;
           int right;
           int mid;
           int color;      
    }node[8*MAX_N];
    int d[8*MAX_N];
    bool boo[10000003];
    int hash[10000003];

    int cmp( const void *a , const void *b ){
        return *(int *)a-*(int *)b;
    }

    void B_Tree( int left , int right , int num ){            //建树
          node[num].left = left;
          node[num].right = right;
          node[num].mid = (left+right)/2;
          node[num].color = 0;
          if( left + 1 != right ){
              B_Tree( left , node[num].mid , 2*num );
              B_Tree( node[num].mid , right , 2*num+1 );   
          }
    }

    void insert( int left , int right , int num , int &sum ){   //插入
        if( node[num].color >= node[num].right - node[num].left ){  //区间是否全部被覆盖
            return ;   
        }
        if( left == node[num].left && right == node[num].right ){
            sum++;
            node[num].color = node[num].right - node[num].left;
            return ;
        }
        if( right <= node[num].mid ){
            insert(left, right, 2*num , sum );
        }else if( left >= node[num].mid ){
              insert( left , right , 2*num+1 , sum );     
        }else{
              insert( left , node[num].mid , 2*num , sum );
              insert( node[num].mid , right , 2*num+1 , sum );    
        }
        node[num].color = node[2*num].color + node[2*num+1].color; //根节点等于它左右子树的和
    }

    int main()
    {   
         int cas , n , i , j ,m;
         scanf("%d",&cas);
         memset( boo , false , sizeof(boo) );
         while( cas-- ){
                scanf("%d",&n);
                m = 0;
                for( i = 1 ; i <= n ; i++ ){
                      scanf("%d%d",&str[i].left,&str[i].right);
                      str[i].right++;
                      if( !boo[str[i].left] ){
                          d[m++] = str[i].left;
                          boo[str[i].left] = true;
                      }
                      if( !boo[str[i].right] ){
                          d[m++] = str[i].right; 
                          boo[str[i].right] = true;
                      }
                }   
                qsort( d , m , sizeof(d[0]) , cmp );
                j = 1;
                for( i = 0 ; i < m ; i++ ){     //离散化过程
                     boo[d[i]] = false;
                     hash[d[i]] = j++;
                }
                int sum = 0;
                B_Tree( 1 , j , 1 );
                for( i = n ; i >= 1 ; i-- ){
                     int k = 0;
                     insert( hash[str[i].left] , hash[str[i].right] , 1 , k );
                     if( k > 0 ){
                           sum++;
                     }
               }
               printf("%d\n",sum);
         }
         return 0;   
    }

  • 相关阅读:
    获取一组radio按钮选中的值Value
    三相异步电动机过载保护及报警PLC控制
    2014年天津市第一批科技计划项目
    USB HID报告及报告描述符简介
    Log Explorer使用说明
    SQL日志文件的作用
    STM32 USB数据接收与数据发送程序流程分析
    多少人没熬过那三厘米!
    构建区域综合交通枢纽 京津冀将形成“一张图”
    Altium Designer下Gerber转PCB的方法(转)
  • 原文地址:https://www.cnblogs.com/cnjy/p/1557350.html
Copyright © 2011-2022 走看看