`

PKU 1177 Picture .

 
阅读更多


 

 Picture
Time Limit: 2000MS   Memory Limit: 10000K
Total Submissions: 7116   Accepted: 3711

Description

A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter.

Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.

The corresponding boundary is the whole set of line segments drawn in Figure 2.

The vertices of all rectangles have integer coordinates.

Input

Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.

0 <= number of rectangles < 5000
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

Output

Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.

Sample Input

7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16

Sample Output

228

Source

呢个系我第一次做线段树离散化求矩形周长并,参考左Var Bob:^Joy关于线段树既文章。

8927215 GZHU1006100106 1177 Accepted 1528K 110MS C++ 3841B 2011-07-19 11:12:09
第一次编110ms效率唔系太高{= =}
 
下面附上代码:
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define MAXI 5005
#define INFI 10005

struct rect { int l, b, r, t; } rec[MAXI];
struct irec { int x, b, t, f; } xi[2 * MAXI];
int n, yi[2 * MAXI];

class segtree
{
    protected :
  struct node
  {
   node *ls, *rs;
   int l, r, c, m, cc;
   bool lb, rb;
  } *root, *p;
 public :
  void make(node *&x)
  {
   x = new node;
   x->ls = NULL;
   x->rs = NULL;
   x->l = x->r = x->c = x->m = x->cc = 0;
   x->lb = x->rb = 0;
  }
  segtree() { root = NULL; }
  int getm() { return root->m; }
  int getcc() { return root->cc; }
  void ins(int a, int b) { sins(root, a, b); }
  void del(int a, int b) { sdel(root, a, b); }
  void inti(int l, int r) { sint(root, l, r); }
  void lata(node *&x, int a, int b)
  {
   if (x->c > 0)
   {
    x->m = yi[x->r] - yi[x->l];
    x->lb = x->rb = x->cc = 1;
   }
   else if (x->c == 0 && x->l + 1 == x->r)
    x->lb = x->rb = x->m = x->cc = 0;
   else
   {
    x->lb = x->ls->lb;
    x->rb = x->rs->rb;
    x->m = x->ls->m + x->rs->m;
    x->cc = x->ls->cc + x->rs->cc;
    if (x->ls->rb == 1 && x->rs->lb == 1) x->cc--;
   }
  }
  void sint(node *&x, int l, int r)
  {
   make(x);
   x->l = l;
   x->r = r;
   if (l + 1 == r) return ;
   sint(x->ls, l, (l + r) / 2);
   sint(x->rs, (l + r) / 2, r);
  }
  void sins(node *&x, int a, int b)
  {
   int m = (x->l + x->r) / 2;
   if (a <= x->l && x->r <= b)
    x->c++;
   else
   {
    if (a < m) sins(x->ls, a, b);
    if (m < b) sins(x->rs, a, b);
   }
   lata(x, a, b);
  }
  void sdel(node *&x, int a, int b)
  {
   int m = (x->l + x->r) / 2;
   if (a <= x->l && x->r <= b)
    x->c--;
   else
   {
    if (a < m) sdel(x->ls, a, b);
    if (m < b) sdel(x->rs, a, b);
   }
   lata(x, a, b);
  }
};

bool operator < (irec &a, irec &b)
{
 if (a.x == b.x) return a.f < b.f;
 else return a.x < b.x;
}

int bs(int key, int l, int r)
{
 int m = (l + r) / 2; 
 if (yi[l] == key) return l;
 if (yi[r] == key) return r;
 if (yi[m] < key) return bs(key, m + 1, r);
 if (yi[m] > key) return bs(key, l, m - 1);
 return m;
}

int stat()
{
 segtree zkl;
 int i, sum = 0, cc = 0, tm = 0;
 zkl.inti(0, 2 * n - 1);
 for (i = 0; i < 2 * n; i++)
 {
  if (xi[i].f) zkl.del(xi[i].b, xi[i].t);
  else zkl.ins(xi[i].b, xi[i].t);

#if 0
  printf("dm = %d, lx = %d m = %d cc = %d dx = %d\n",
      zkl.getm() - tm,
      2 * (xi[i].x - xi[i - 1].x) * cc,
      zkl.getm(),
      cc,
      xi[i].x - xi[i - 1].x);
#endif

  sum += 2 * (xi[i].x - xi[i - 1].x) * cc;
  sum += abs(zkl.getm() - tm);
  tm = zkl.getm();
  cc = zkl.getcc();
 }
 return sum;
}

int main()
{
 int i, j;

 while (scanf("%d", &n) != EOF)
 {
  //Discrete Begin
  for (j = i = 0; i < n; i++)
  {
   scanf("%d%d%d%d",
      &rec[i].l,
      &rec[i].b,
      &rec[i].r,
      &rec[i].t);
   yi[j++] = rec[i].b;
   yi[j++] = rec[i].t;
  }
  sort(yi, yi + n * 2);
  //Discrete End
  //Event Sort Begin
  for (j = i = 0; i < n; i++)
  {
   xi[j].x = rec[i].l;
   xi[j].b = bs(rec[i].b, 0, 2 * n - 1);
   xi[j].t = bs(rec[i].t, 0, 2 * n - 1);
   xi[j++].f = 0;
   xi[j].x = rec[i].r;
   xi[j].b = xi[j - 1].b;
   xi[j].t = xi[j - 1].t;
   xi[j++].f = 1;
  }
  sort(xi, xi + n * 2);
  //Event Sort End

#if 0
  for (i = 0; i < n * 2; i++)
   printf("%d ", yi[i]);
  putchar('\n');
  for (i = 0; i < n * 2; i++)
   printf("%d ", xi[i].x);
  putchar('\n');
  for (i = 0; i < n * 2; i++)
   printf("x = %d, b = %d, t = %d, f = %d\n",
          xi[i].x, xi[i].b, xi[i].t, xi[i].f);
#endif
  printf("%d\n", stat());
 }

 return 0;
}

 
代码比较长= =,带有宏开关既系测试输出代码。
其实思想都唔系好复杂,我主要系想讲下离散化:
离散化既出现其实就系为左节省空间,好似上面果题甘样,线段树本来就唔系咩微型数据结构,如果吾离散化,实在会爆到恒{= =}。
做法有滴类似组合数学里面既一一对应,姐系等价转换,不过要保留原型,因为统计要用。
 
例如:
题目坐标范围【-10w, 10w】直接既捻法就系开一个20w大既线段树,但系加上卫星数据好明显会爆炸{= =}
我地再留意一下题目里面矩形数目既范围为5000,亦即有效坐标系最多1w个坐标,何必开20w呢?
所以我地可以做如下工作节省空间:
 
//Discrete Begin
  for (j = i = 0; i < n; i++)
  {
   scanf("%d%d%d%d",
      &rec[i].l,
      &rec[i].b,
      &rec[i].r,
      &rec[i].t);
   yi[j++] = rec[i].b;
   yi[j++] = rec[i].t;
  }
  sort(yi, yi + n * 2);
  //Discrete End
应该好容易睇出步骤就系先用数组yi储存所有矩形既y轴坐标,然后用sort排序, 得到如下序列:
 
实际数据:-6 -4 0 0 4 8 10 10 14 15 16 20 22 25
数据位置:0    1 2 3 4 5  6   7    8    9  10 11 12 13
 
跟住又注意到位置大小其实对应实际大小,所以我地储存既时候完全可以用位置“等效替代”实际数据{= =+}。
 
下面讲讲如何替代:
其实就系憨鸠鸠甘样开过另外一个数组直接二分查找代替原有y轴坐标{=_. =}
//Event Sort Begin
  for (j = i = 0; i < n; i++)
  {
   xi[j].x = rec[i].l;
   xi[j].b = bs(rec[i].b, 0, 2 * n - 1);
   xi[j].t = bs(rec[i].t, 0, 2 * n - 1);
   xi[j++].f = 0;
   xi[j].x = rec[i].r;
   xi[j].b = xi[j - 1].b;
   xi[j].t = xi[j - 1].t;
   xi[j++].f = 1;
  }
  sort(xi, xi + n * 2);
  //Event Sort End
 
关于线段树解决矩形问题baidu一下大把,有了解既应该知道呢类算法既一种感性理解就系想象有一条竖直扫描线,将矩形班油仔从左向右扫描一次
取得一滴统计数据。扫描数组xi其实模拟呢个。
注意到记录x坐标上y线段t(top)同埋b(bottom)既时候就用左bs(BinarySearch)用位置等效替代。
之后我地就可以直接使用呢滴相对位置鸟。
 
所以离散化其实系一样好简单既野,就系个名吓人一滴。
仲有我觉得叫离散化好似有滴怪,因为距实际操作系压缩坐标 {= =}
  • 大小: 17.7 KB
  • 大小: 17.8 KB
分享到:
评论

相关推荐

    pku_training.utf8

    此数据集用于NLP中分词训练使用,文档中的文字已经人工切分好词组,总共有65536个中国汉字组合而成

    PKU-ACM.rar_PKU_acm 题目

    在编程竞赛的世界里,北京大学(PKU)的ACM团队以其高质量的题目和独特的解题思路闻名。"PKU-ACM.rar"这个压缩包包含了北大ACM题目的一些核心知识点,旨在帮助参赛者理解和掌握算法竞赛中的生命周期题目解法。本文将...

    EMF.Eclipse Modeling Framework.2nd.PKU.SEI.SA.part2

    EMF.Eclipse Modeling Framework.2nd.PKU.SEI.SA.part2

    EMF.Eclipse Modeling Framework.2nd.PKU.SEI.SA.part1

    EMF.Eclipse Modeling Framework.2nd.PKU.SEI.SA.part1

    穿梭到北大未名(bbs.pku.edu.cn)的穿梭服务器程序

    本软件是一个穿梭到北大未名(bbs.pku.edu.cn)的穿梭服务器程序。北大校内用安装本软件后,别人就可以通过telenet您自己的机器而登陆到北大未名bbs了. 本软件占用内存极少,通常是1到2M; 占用CPU时间约为0.01%。 A....

    ACM.PKU解题报告.part2

    ACM.PKU解题报告.part2

    acm_pku_code.zip_Code p_acm pku_acm pku pu_acm.pku_pku acm

    "p_acm"、"pku_acm"以及"pu_acm.pku_pku"等标签可能是用于分类或标识这些代码属于北京大学(Peking University, PKU)的ACM训练题目。"acm"一词重复出现,进一步强调了这是关于ACM编程竞赛的内容。 描述中提到"acmer...

    深度优先遍历 搜索算法 ACM PKU 1011 S.doc

    深度优先遍历 搜索算法 ACM PKU 1011 S.doc

    PKU_2411.rar_2411 p_pku 2411

    标题中的“PKU_2411.rar_2411 p_pku 2411”似乎是指北京大学(Peking University, 简称PKU)的一个课程或比赛编号2411,其中包含了“rar”后缀的压缩文件。这个压缩包可能包含了该课程或活动的相关资料,如作业、项目...

    PKU+ACM.rar_ACM_PKU_acm pku_acm 北大_site:www.pudn.com

    北京大学(PKU)在计算机科学领域享有盛誉,其在ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest, ICPC)方面的成就更是备受瞩目。"PKU+ACM.rar"这个压缩包显然包含了与北大ACM竞赛相关...

    数据结构与算法课件 北大张铭 DS_02

    - 实验班讲义和作业发布(包括实习作业):`http://db.pku.edu.cn/mzhang/ds/honor/` - 实习课讲义和作业发布:`http://db.pku.edu.cn/mzhang/DS/shixi/` 这些资源提供了学习者获取课程材料及提交作业的方式,有...

    pku题目分类.doc

    这份"Pku题目分类.doc"文件提供了北京大学(Peking University, PKU)编程竞赛中的一些题目分类,涵盖了许多不同的算法和问题类型。以下是对这些标签和题目类型的详细解释: 1. **送分题**:这类题目通常相对简单,...

    PKU的csapp.zip

    这个名为"PKU的csapp.zip"的压缩包文件显然包含了与北京大学(Peking University,简称PKU)相关的CSAPP课程相关的学习资源,特别是针对期末考试的复习材料。 首先,我们可以从"体系结构"这一标签中挖掘出以下几个...

    pku_ACM.rar_PKU_PKU_ACM

    《北京大学PKU ACM竞赛题目解析》 北京大学(Peking University, 简称PKU)作为中国顶级学府,其在计算机科学领域的教育和竞赛有着深厚的底蕴。ACM(International Collegiate Programming Contest,国际大学生程序...

    ACM-PKU-DP.zip_源码

    标题中的"ACM-PKU-DP.zip_源码"表明这是一个与算法竞赛相关的压缩包,特别是北京大学(PKU)的动态规划(DP)问题的源代码集合。动态规划是一种解决复杂问题的有效方法,通常用于优化决策过程,通过将大问题分解为多...

    苯丙酮尿症PKU实施方案.pptx

    苯丙酮尿症(PKU)是一种罕见的遗传性代谢疾病,主要影响氨基酸代谢路径,导致苯丙氨酸无法正常转化为酪氨酸,进而积累过多的苯丙酮酸在体内,对神经系统造成损害,尤其是对儿童的智力发展有严重影响。新生儿疾病...

    ACM.PKU解题报告.part1

    ACM PKU 解题报告 锻炼算法的好东西! 前面的很多题的解题报告。

    ACM学习资料汇总,ACMer要试试哦!

    - [题目2](http://acm.pku.edu.cn/JudgeOnline/problem?id=2288) —— 经典的旅行商问题(TSP),需要考虑如何找到一个最小化的环路。 - [题目3](http://acm.pku.edu.cn/JudgeOnline/problem?id=2411) —— 状态压缩...

    POJ.rar_pku ac_pku.1050

    标题中的"POJ.rar_pku ac_pku.1050"暗示了这是一个与北京大学(Peking University, 简称PKU)编程竞赛相关的压缩文件,其中包含了作者通过验证(Passed All Cases, 简称AC)的代码,具体是针对PKU题目编号1050的问题。...

Global site tag (gtag.js) - Google Analytics