【線段樹】Mayor's posters

2023-11-06

Description
The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election
campaign have been placing their electoral posters at all places at their whim. The city
council has finally decided to build an electoral 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 for all candidates). 
When the electoral campaign was restarted, the candidates were placing their posters on the
wall and their posters differed widely in width. Moreover, the candidates started placing their
posters on wall segments already occupied by other posters. Everyone in Bytetown was curious
whose posters will be 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 are placed given the
information about posters' size, their place and order of placement on the electoral wall.

Input
The first line of input contains a number c giving the number of cases that follow. The first
line of data for a single case contains number 1 <= n <= 10000. The subsequent 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 wall segment 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-th poster is placed, it entirely covers all wall 
segments numbered li, li+1 ,... , ri.

Output
For each input data set print the number of visible posters after all the posters are placed.

The picture below illustrates the case of the sample input. 

Sample Input

1
5
1 4
2 6
8 10
3 4
7 10

Sample Output

4
這個題做了很久,還是看了別人的解題報告才做出來的。

思路很簡單,區間離散化+線段樹。

樸素方法(O(m^2)):枚舉牆上的每一個位置,從最後一張海報倒回去找看最先被哪張海報覆蓋,最後統計顏色,但看一看數據,0..10000000,無疑是一個天文數字!

於是需要優化。

優化1:通過觀察可以發現,對於如下幾個區間:[1, 10], [2, 11], [3, 23],中間的很大一部分(如[3, 9]和[11, 23]),這些地方是被白白浪費掉了的!
於是可以將這些部分舍掉,即將這幾個區間分別變成[1, 4], [2, 5], [3, 6],這樣既沒有改變區間之間的覆蓋關係,又大大減少枚舉量。
優化2:使用線段樹。
區間統計問題大都可以通過線段樹進行優化,當整個區間為單色時,就不需要對其子區間進行遍曆。
Accode:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <bitset>

using std::bitset;

const char fi[] = "poj2528.in";
const char fo[] = "poj2528.out";
const int maxN = 10010;
const int MAX = 0x3fffff00;
const int MIN = -MAX;

struct SegTree {int L, R, lc, rc, color; };
struct Seg {int pos, Ind, sym; };

SegTree tree[maxN << 3];
Seg seg[maxN << 1];
bitset <maxN> marked;
int L[maxN], R[maxN];
int n, N, tot, cnt;

  void init_file()
  {
    freopen(fi, "r", stdin);
    freopen(fo, "w", stdout);
  }
  
  int cmp(const void *a, const void *b)
    {return ((Seg *)a) -> pos - ((Seg *)b) -> pos; }
  
  void Build(int L, int R)
  {
    int Now = ++tot;
    tree[Now].L = L;
    tree[Now].R = R;
    tree[Now].lc = 0;
    tree[Now].rc = 0;
    tree[Now].color = 0;
	//所有標記清零。
    if (L + 1 < R)
    {
      int Mid = (L + R) >> 1;
      tree[Now].lc = tot + 1;
      Build(L, Mid);
      tree[Now].rc = tot + 1;
      Build(Mid, R);
    }
	//遞歸建樹。
  }
  
  void insert(int Now, int i)
  {
    if (L[i] > tree[Now].R || R[i] < tree[Now].L)
      return;
	//若當前被插入的線段與這個區間無
	//交集,則不需要遍曆。
    if (L[i] <= tree[Now].L && R[i] >= tree[Now].R)
      {tree[Now].color = i; return; }
	//若該區間被完全覆蓋,直接染色並退出。
    if (tree[Now].color > -1)
    {
      tree[tree[Now].lc].color =
        tree[tree[Now].rc].color =
        tree[Now].color;
      tree[Now].color = -1;
    }	//若開始時該區間為單色或無色,
	//則標記向下傳,並把該區間標記為多色。
    int Mid = (tree[Now].L + tree[Now].R) >> 1;
    if (L[i] < Mid) insert(tree[Now].lc, i);
    if (Mid < R[i]) insert(tree[Now].rc, i);
	//依次對它的左右子區間進行統計。
  }
  
  void count(int Now)
  {
    if (tree[Now].color == 0) return;
	//如果該區間沒有顏色,
	//那麼其子區間不需要被遍曆。
    if (tree[Now].color > 0)
    {
      if (!marked.test(tree[Now].color))
        {marked.set(tree[Now].color); ++cnt; }
      return;
    }	//若該區間為單色,統計該顏色後
	//就不需要對其子區間進行統計了。
    if (tree[Now].lc) count(tree[Now].lc);
    if (tree[Now].rc) count(tree[Now].rc);
	//若該區間為多色,那麼需要對各個子區間
	//分別進行統計。
  }
  
  void work()
  {
    scanf("%d", &N);
    for (; N; --N)
    {
      scanf("%d", &n);
      int x, y;
      tot = 0;
      for (int i = 1; i < n + 1; ++i)
      {
        scanf("%d%d", &x, &y);
        seg[++tot].pos = x;
        seg[tot].sym = 1;
        seg[tot].Ind = i;
        seg[++tot].pos = y + 1;
        seg[tot].sym = -1;
        seg[tot].Ind = i;
      }
      qsort(seg + 1, n << 1,
        sizeof(seg[0]), cmp);
	//按照座標從左到右排序,方便壓縮。
      int Last = 1;
      if (seg[1].sym == 1)
        L[seg[1].Ind] = 1;
      if (seg[1].sym == -1)
        R[seg[1].Ind] = 1;
      for (int i = 2; i < (n << 1) + 1; ++i)
      {
        if (seg[i].pos == seg[i - 1].pos)
        {
          if (seg[i].sym == 1)
            L[seg[i].Ind] = Last;
          if (seg[i].sym == -1)
            R[seg[i].Ind] = Last;
        }
        if (seg[i].pos > seg[i - 1].pos)
	//壓縮區間,“毀掉”不需要用掉的空間。
        {
          if (seg[i].sym == 1)
            L[seg[i].Ind] = ++Last;
          if (seg[i].sym == -1)
            R[seg[i].Ind] = ++Last;
        }
      }
      tot = 0;
      Build(1, Last);
	//建立線段樹。
      for (int i = 1; i < n + 1; ++i)
        insert(1, i);
      marked.reset();
      cnt = 0;
      count(1);
      printf("%d\n", cnt);
    }
  }
  
int main()
{
  init_file();
  work();
  exit(0);
}



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【線段樹】Mayor's posters 的相关文章

随机推荐

  • Cadence 背景颜色设置

    目录 概述 一 Allegro PCB Designer 二 OrCAD Capture 三 总结 概述 有位粉丝问我 关于背景颜色设置问题 这里我写一篇文章吧 尽自己微薄之力帮助更多的人 加油 一 Allegro PCB Designer
  • 2.22笔记:linux命令不同颜色命令

    浅蓝色 表示软链接 灰色 表示其他文件 绿色 表示可执行文件 红色 表示压缩文件 蓝色 表示目录 红色闪烁 表示链接的文件有问题了 黄色 表示设备文件 包括block char fifo 管道文件 粉色 网络文件
  • bochs+gdb联调linux-0.11内核

    终于把bochs和gdb连起来了 下面描述下步骤以作记录 1 安装bochs 前面有篇文章介绍了bochs源码编译安装过程 这里安装也非常相似 只是命令稍微有些不同 configure enable gdb stub make make i
  • Java语言连接数据库时间读取错误的问题

    连接时候的数据库相关配置
  • pcie inbound和outbound关系

    Inbound PCI域訪问存储器域 Outbound 存储器域訪问PCI域 RC訪问EP RC存储器域 gt outbound gt RC PCI域 gt EP PCI域 gt inbound gt EP存储器域 EP訪问RC EP存储器
  • Jenkins插件下载失败两种处理办法

    持续集成 自动化部署 弹性伸缩教程 http edu csdn net course detail 6452 大家在使用jenkins安装插件的时候经常遇到一下问题 就是插件由于网络或者墙的原因无法直接下载 出现下面截图的问题 处理办法有两
  • flume采集log4j日志到kafka

    简单测试项目 1 新建Java项目结构如下 测试类FlumeTest代码如下 package com demo flume import org apache log4j Logger public class FlumeTest priv
  • 芯片电源引脚为什么要加一个100nF电容

    在设计电路的时候 常常会在芯片的每个电源引脚就近的放一个100nF的贴片电容 这电容有什么作用呢 今天就来和大家分享一下这个电容的作用以及为什么是100nF 首先这个芯片电源引脚的100nF的电容一般我们称为旁路电容 也有叫去耦电容的 因为
  • Oracle 行转列 动态出转换的列

    10月的第二天 前天写了个Oracle中行转列的pivot的基本使用方法 然后 因为pivot的用法中 正常情况下 我们需要转出多少个列 都得在我们的sql中完完整整地写出 而不能直接在里面写个查询来动态转换 然后 趁着祖国母亲的生日 这几
  • 漫谈设计模式之建造者模式(Builder)

    建造者模式 Builder 又叫生成器模式 属于对象创建型模式 建造者模式的目的是要将一个复杂对象的构建与它的表示分离 使得同样的构建过程可以创建不同的表示 产品 说得通俗点就是一个产品 表示 的构建 生产 过程是一样的 但是同样的生产过程
  • hdu 1465不容易系列之一

    http acm hdu edu cn showproblem php pid 1465 这是一道排错问题 用排错公式 排错公式推导 当n个编号元素放在n个编号位置 元素编号与位置编号各不对应的方法数用D n 表示 那么D n 1 就表示n
  • FISCO BCOS 2.0原理解析: 群组架构的设计

    为了方便企业 开发者更深入理解FISCO BCOS 2 0诸多新特性 更快速地运用FISCO BCOS搭建联盟链应用 我们启动了FISCO BCOS 2 0系列剖析的计划 在后续的推送中 我们将陆续推出 FISCO BCOS 2 0原理解析
  • LeetCode 260. 只出现一次的数字 III

    题目链接 https leetcode cn problems single number iii 思路如下 从头到尾依次异或数组中的每一个数字 那么最终得到的结果就是两个只出现一次的数字的异或结果 因为其他数字都出现了两次 在异或中全部抵
  • javascript求任意一组数的平均值

    代码 function getAvg 任意一组数求平均值 var sum 0 len arguments length i arguments是js函数中内置的类数组 它能像数组一样使用下标进行访问元素 for i 0 i
  • vue怎么改logo_vue项目添加网页logo

    网上关于为vue项目添加网页logo的文章很多 步骤很简单 但是博主还是踩了坑 特此记录一下 先上效果 1 首先 要为网页添加logo我们需要一张ico格式的图标 可以用网上的在线转换工具 将 jpg png 格式的图片转为 ico 格式
  • 防抖与节流函数

    文章目录 前言 节流函数代码 防抖函数代码 前言 防抖与节流是日常开发中常用的两个函数 目的都在于控制事件触发频率降低性能损耗和代码错误 节流 点击事件即开始计时 计时时间内无论触发多少次事件 都只执行触发计时的那个事件 防抖 点击事件即开
  • Python: SQLAlchemy 增、删、改、查

    目录 一 完整代码 1 1 代码 1 2 运行结果 二 增删改查 2 1 增加一行记录 2 2 修改一行记录 2 3 查询一行记录 2 4 删除一行记录 一 完整代码 1 1 代码 import uuid import datetime i
  • 一个关于缓存的问题

    网上查了一下 关于生命周期的话题 如果是类的成员变量 则其声明周期贯穿整个其对象的生命周期 如果是方法内的变量 局部变量 则仅仅在该方法内有效 出了方法体则无效 失去意义 static是修饰静态代码块或者成员变量或者方法的 其方法或者代码块
  • 介绍一个十分牛逼的GitHub看代码神器,零基础必学会的操作。

    给大家介绍一个非常实用的工具 有了它 我们可以在几秒之内用 VS Code 打开 GitHub 上的任意一个 Repo 无需 Clone 速度飞快 用法也十分简单而且好记 下面给大家介绍下 介绍 比如这里是 Scrapy 的仓库 https
  • 【線段樹】Mayor's posters

    Description The citizens of Bytetown AB could not stand that the candidates in the mayoral election campaign have been p