poj 2528

来源:互联网 发布:数据分析的具体流程 编辑:程序博客网 时间:2024/05/22 10:36

Description

Thecitizens of Bytetown, AB, could not stand that the candidates inthe mayoral election campaign have been placing their electoral posters at allplaces at their whim. The city council has finally decided to build anelectoral wall for placing the posters and introduce the following rules: 

  • Every candidate can place exactly one poster on the wall. 
  • All posters are of the same height equal to the height of the wall; the width of a poster can be any integer number of bytes (byte is the unit of length in Bytetown). 
  • The wall is divided into segments and the width of each segment is one byte. 
  • Each poster must completely cover a contiguous number of wall segments.


They have built a wall 10000000 bytes long (such that there is enough place forall candidates). When the electoral campaign was restarted, the candidates wereplacing their posters on the wall and their posters differed widely in width.Moreover, the candidates started placing their posters on wall segments alreadyoccupied by other posters. Everyone in Bytetown was curious whose posters willbe visible (entirely or in part) on the last day before elections. 
Your task is to find the number of visible posters when all the posters areplaced given the information about posters' size, their place and order ofplacement on the electoral wall. 

Input

The firstline of input contains a number c giving the number of cases that follow. Thefirst line of data for a single case contains number 1 <= n <= 10000. Thesubsequent n lines describe the posters in the order in which they were placed.The i-th line among the n lines contains two integer numbers li and ri which are the number of the wallsegment occupied by the left end and the right end of the i-th poster,respectively. We know that for each 1 <= i <= n, 1 <= li <= ri <= 10000000. After the i-thposter is placed, it entirely covers all wall segments numbered li,li+1 ,... , ri.

题目大意:

往一面墙上(有整齐的瓷砖)贴海报,有些海报会覆盖别的海报,覆盖的可能是全部覆盖,也可能是部分覆盖,分组输入海报左右端点,问有多少张海报没有被完全覆盖。

代码如下:

#include <iostream>

#include <algorithm>

#include <math.h>

using namespace std ;

int n ;

struct Post

{

   int L, R ;

};

Post posters[10000] ;

int x[20000] ;

int ahash[10000000] ;

struct Node

{

   int L, R ;

   bool Covered ;

   Node *pLeft, *pRight ;

};

Node Tree[1000000] ;

int nNodeCount = 0 ;

int Mid(Node *pRoot)

{

   return (pRoot->L + pRoot->R)/2 ;

}

void BuildTree(Node *pRoot, int L, int R)

{

   pRoot->L = L ;

   pRoot->R = R ;

   pRoot->Covered = false ;

   if(L == R)

       return ;

   nNodeCount++ ;

   pRoot->pLeft = Tree + nNodeCount ;

   nNodeCount++ ;

   pRoot->pRight = Tree + nNodeCount ;

   BuildTree(pRoot->pLeft, L, (L+R)/2) ;

   BuildTree(pRoot->pRight, (L+R)/2+1, R) ;

}

bool Fpost(Node *pRoot, int L, int R)

{

   if(pRoot->Covered)

       return false ;

   if(pRoot->L == L && pRoot->R == R)

    {

       pRoot->Covered = true ;

       return true ;

    }

   bool bResult ;

   if(R <= Mid(pRoot))

       bResult = Fpost(pRoot->pLeft, L, R) ;

   else if(L > Mid(pRoot))

       bResult = Fpost(pRoot->pRight, L, R) ;

   else

    {

       bool b1 = Fpost(pRoot->pLeft, L, Mid(pRoot)) ;

       bool b2 = Fpost(pRoot->pRight, Mid(pRoot)+1, R) ;

       bResult = b1 || b2 ;

    }

   if(pRoot->pLeft->Covered && pRoot->pRight->Covered)

       pRoot->Covered = true ;

   return bResult ;

}

int main()

{

   int t ;

   int i, j, k ;

scanf("%d",&t) ;

while(t--)

    {

       nCaseNo++ ;

       scanf("%d", &n) ;

       for(i = 0; i < n; i++)

       {

           scanf("%d%d", &posters[i].L, &posters[i].R) ;

           x[nCount++] = posters[i].L ;

           x[nCount++] = posters[i].R ;

       }

       sort(x, x + nCount) ;

       nCount = unique(x, x + nCount) - x ;

       int nlntervcalNo = 0 ;

       for(i = 0; i < nCount; i++)

       {

           ahash[x[i]] = nlntervcalNo ;

                if(x[i+1] - x[i] == 1)

                    nlntervcalNo++ ;

                else

                    nlntervcalNo += 2 ;

       }

       BuildTree(Tree, 0, nlntervcalNo) ;

       int sum = 1 ;

       for(i = n - 1; i >= 0; i--)

       {

           if(Fpost(Tree, ahash[posters[i].R], ahash[posters[i].R]))

                sum ++ ;

       }

        printf("%d\n", sum) ;

    }

   return 0 ;

}

 

结构体

struct Post

{

   int L, R ;

}; 用来存放每一个海报的左右端点。

struct Node

{

   int L, R ;

   bool Covered ;

   Node *pLeft, *pRight ;

}; 结点,以所有海报所覆盖的瓷砖数来建立线段树。Covered变量表示该节点所表示区间【L,R】是否已经全部覆盖。

Main函数中,将每个海报的左右端点按输入顺序存到x数组中,然后将x数组中的数排序sort(),在排序过程中,海报的右端点一定比左端点表示的数大;可能有某几张海报的端点一样,x数组有重复元素,unique()函数将重复元素剔除,

int nlntervcalNo = 0 ;

       for(i = 0; i < nCount; i++)

       {

           ahash[x[i]] = nlntervcalNo ;

                if(x[i+1] - x[i] == 1)

                   nlntervcalNo++ ;

                else

                    nlntervcalNo += 2 ;

       }

这是将海报所覆盖范围确定出来,并将海报所覆盖的瓷砖范围离散化,相当于数学上的一个“数形结合”的过程,然后建立线段树BuildTree() ;

Fpost()函数中:

bResult = b1 || b2 ;表示海报覆盖范围中只要有一部分没被其他海报覆盖,就表示这张海报的某个区间海报可见。

0 0
原创粉丝点击