ACM_9Poster

来源:互联网 发布:sql配置管理器在哪 编辑:程序博客网 时间:2024/06/05 01:03

posters

时间限制:1000 ms  内存限制:65535KB
难度:6
描述
The citizens of Bytetown, AB, could not stand that thecandidates in the mayoral election campaign have been placing theirelectoral posters at all places at their whim. The city council hasfinally decided to build an electoral wall for placing the postersand 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 thewall; 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 segmentis one byte.
• Each poster must completely cover a contiguous number of wallsegments.

They have built a wall 10000000 bytes long (such that there isenough place for all candidates). When the electoral campaign wasrestarted, the candidates were placing their posters on the walland their posters differed widely in width. Moreover, thecandidates started placing their posters on wall segments alreadyoccupied by other posters. Everyone in Bytetown was curious whoseposters will be visible (entirely or in part) on the last daybefore elections.
Your task is to find the number of visible posters when all theposters are placed given the information about posters' size, theirplace and order of placement on the electoral wall.
输入
The first line of input contains a number c giving the numberof cases that follow. The first line of data for a single casecontains number 1 <= n <= 10000. The subsequent n linesdescribe the posters in the order in which they were placed. Thei-th line among the n lines contains two integer numbers li and riwhich are the number of the wall segment occupied by the left endand the right end of the i-th poster, respectively. We know thatfor each 1 <= i <= n, 1 <= li <= ri <= 10000000.After the i-th poster is placed, it entirely covers all wallsegments numbered li, li+1 ,... , ri.
输出
For each input data set print the number of visible postersafter all the posters are placed.

The picture below illustrates the case of the sample input.
http://acm.pku.edu.cn/JudgeOnline/images/2528_1.jpg
样例输入
151 42 68 103 47 10
样例输出
4
来源
POJ
上传者
iphxer

      这道题用到了线段树和离散化2个概念,1方面帖海报的过程就是对线段的节点进行染色的过程,另外一方面申请1000K的墙这个对内存的消耗太大了,并且在检索的时候效率也很低,这时候考虑到海报只有1W,那么我们可以针对海报做处理,思考最后的结果,每一块海报张贴的区域应该是可以由开始节点和结束节点确定的,那么我们需要考虑的点做多只有2W,但是这时候要考虑如果我们对海报的开始和结束位置进行离散化那么就有一些信息丢失掉了,比如如下两组数据

1-10 1-4 5-10

1-10 1-4 6-10

第一个案例运气好还能通过,第二个案例在对顶点离散完之后剩  1 4 610   5-5这段区域被丢失掉了,这块区域总是出现在某一个海报末尾之后连续区域,我们可以用那张海报的末尾节点+1来表示这块区域,那么我们可以将所有末尾节点加一加入原始数据再对数据进行离散,这样原始数据就不会丢失了,一下是实现代码


import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

//线段树的实现
public class PosterV1 {
    intsize;
    intnodes;
    final intmaxn = 11111;
    boolean[]statistic = new boolean[maxn];
    int[]leftVertux = new int[maxn];
    int[]rightVertux = new int[maxn];
    int[] tree =new int[maxn << 4];
    ArrayListtemp = new ArrayList(maxn*3);

    publicstatic void main(String[] args) {
       PosterV1poster = new PosterV1();
      poster.solution();
    }

    //程序入口
    public voidsolution() {
       Scanner in =new Scanner(System.in);
       int cases =in.nextInt();
       while(cases-- > 0) {
         init();

          //获取海报的左右坐标
          nodes =in.nextInt();
          for (int i =1; i <= nodes; i++) {
            leftVertux[i] = in.nextInt();
            rightVertux[i] = in.nextInt();
            temp.add(leftVertux[i]);
            temp.add(rightVertux[i]);
          }
          //将海报的坐标离散化, 这里用到的处理丢失数据的方案比我上面分析的要差
         Collections.sort(temp);
          for (int i =1; i < temp.size(); i++) {
             if(temp.get(i) == temp.get(i - 1)) {
               temp.remove(i);
                i--;
             }
          }
          int dataSize= temp.size();
          for (int i =1; i < dataSize; i++) {
             if(temp.get(i) != temp.get(i - 1) + 1) {
               temp.add(temp.get(i - 1) + 1);
             }
          }
         Collections.sort(temp);
           size = temp.size();
           
          for (int i =1; i <= nodes; i++) {
            Update(getIndex(leftVertux[i]), getIndex(rightVertux[i]), i);
          }
           System.out.println(Query(1, size));
       }
    }

    private intgetIndex(int value) {
       int left =0;
       int right =temp.size() - 1;
       int mid =(left + right) >> 1;

       while (right>= left) {
          if(temp.get(mid) == value) {
             return mid +1;
          } else if(temp.get(mid) > value) {
             right = mid- 1;
          } else{
             left = mid +1;
          }
          mid = (right+ left) >> 1;
       }
       return0;
    }

    //初始化用
    private voidinit() {
       for (int i =1; i <= Math.min(4 * size,maxn<<4); i++) {
          tree[i] =0;
       }
       for (int i =1; i <=nodes ; i++) {
          statistic[i]= false;
       }
      temp.clear();
       size =0;
    }

    //成段跟新
    public voidUpdate(int n, int m, int value) {
       Update(1, 1,size, n, m, value);
    }

    private voidUpdate(int index, int left, int right, int n, int m, int value){
       if (left>= n && right <= m) {
          tree[index]= value;
         return;
       } else{
          if(left==  right){
            return;
          }
         if(tree[index] != 0){
             tree[index<< 1] = tree[index];
             tree[index<< 1 | 1] = tree[index];
             tree[index]= 0;
          }
          int mid =(left + right) >> 1;
          if (mid>= n && left <= m) {
             Update(index<< 1, left, mid, n, m, value);
          }
          if (mid <m && right >= n) {
             Update(index<< 1 | 1, mid + 1, right, n, m, value);
          }
       }
    }

    //差选线段起止之间的不同数的数量
    public intQuery(int start, int end) {
       returnQuery(1, 1, size, start, end);
    }

    private intQuery(int index, int left, int right, int start, int end) {
        if(tree[index] == 0) {
          if(left ==right){
             return0;
          }
          int sum =0;
          if (left>= start && right <= end) {
             int mid =(left + right) >> 1;
             sum +=Query(index << 1, left, mid, start, end);
             sum +=Query(index << 1 | 1, mid + 1, right, start, end);
             returnsum;
          }
          int mid =(left + right) >> 1;
          if (mid>= start && left <= end) {
             sum +=Query(index << 1, left, mid, start, end);
          }
          if (mid <end && right >= start) {
             sum +=Query(index << 1 | 1, mid + 1, right, start, end);
          }
          returnsum;
       } else{
          if (left<= end || right >= start) {
             if(!statistic[tree[index]]) {
               statistic[tree[index]] = true;
                return1;
             } else{
                return0;
             }
          } else{
             return0;
          }
       }

    }

}


0 0
原创粉丝点击