zoukankan      html  css  js  c++  java
  • [线段树]picture

    PICTURE

    题目描述

    N(N<5000) 张矩形的海报,照片和其他同样形状的图片贴在墙上。它们的边都是垂直的或水平的。每个矩形可以部分或者全部覆盖其他矩形。所有的矩形组成的集合的轮廓称为周长。写一个程序计算周长。

    图 1 是一个有 7 个矩形的例子:

    图 1.一个 7 个矩形的集合对应的轮廓为图 2 所示的所有线段的集合:

    图 2. 矩形集合的轮廓

    所有矩形的顶点坐标均为整数。所有的坐标都在 [-10000,10000] 的范围内,并且任何一个矩形面积都为整数。结果的值可能需要 32 位有符号整数表示。

    输入

    第1行: N,张贴在墙上的矩形的数目。 第 2..N+1行 接下来的N行中,每行都有两个点的坐标,分别是矩形的左下角坐标和右上角坐标。每一个坐标由 X 坐标和 Y 坐标组成。

    输出

    只有一行,为一个非负整数,表示输入数据中所有矩形集合的轮廓长度。

    样例输入

    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

    样例输出

    228




    自己写(chao)的,并没有用线段树维护,加了快读8ms
     1 #include <cstdio> 
     2 #include <algorithm> 
     3 #include <cstring> 
     4 using namespace std; 
     5     
     6 struct data { 
     7     int lx, rx; 
     8     int ly, ry; 
     9 }; 
    10     
    11 const int maxn = 5000, maxx = 20000; 
    12 int n; 
    13 data a[maxn + 1]; 
    14 int level[maxx + 1]; 
    15     
    16 bool cmp_x(data x, data y) { 
    17     return x.lx < y.lx; 
    18 } 
    19     
    20 bool cmp_y(data x, data y) { 
    21     return x.ly < y.ly; 
    22 } 
    23     
    24 int in() { 
    25     int f = 1, p = 0;     
    26     char c; 
    27     while (c < '0' || c > '9') {
    28         c = getchar(); 
    29         if (c == '-') {
    30             f = -1; 
    31         }
    32     }
    33     while (c >= '0' && c <= '9') {
    34         p = p * 10 + c - '0'; 
    35         c = getchar(); 
    36     }
    37     p *= f; 
    38     return p; 
    39 } 
    40     
    41 void init() { 
    42     n = in(); 
    43     for (int i = 1; i <= n; i++) { 
    44         a[i].lx = in();
    45         a[i].ly = in();
    46         a[i].rx = in();
    47         a[i].ry = in();  
    48         a[i].lx += 10001; 
    49         a[i].ly += 10001; 
    50         a[i].rx += 10001; 
    51         a[i].ry += 10001; 
    52     } 
    53 } 
    54     
    55 int solve_x() { 
    56     memset(level, -1, sizeof(level)); 
    57     int ans = 0; 
    58     sort(a + 1, a + 1 + n, cmp_x); 
    59     for (int i = 1; i <= n; i++) {
    60         for (int j = a[i].ly; j < a[i].ry; j++) { 
    61             if (level[j] < a[i].lx) {
    62                 ans += 2; 
    63             }
    64             if (level[j] < a[i].rx) {
    65                 level[j] = a[i].rx; 
    66             }
    67         } 
    68     }
    69     return ans; 
    70 } 
    71     
    72 int solve_y() { 
    73     memset(level, -1, sizeof(level)); 
    74     int ans = 0; 
    75     sort(a + 1, a + 1 + n, cmp_y); 
    76     for (int i = 1; i <= n; i++) {
    77         for (int j = a[i].lx; j < a[i].rx; j++) { 
    78             if (level[j] < a[i].ly) { 
    79                 ans += 2; 
    80             }
    81             if (level[j] < a[i].ry) {
    82                 level[j] = a[i].ry; 
    83             }
    84         } 
    85     }
    86     return ans; 
    87 } 
    88     
    89 int main() { 
    90     init(); 
    91     printf("%d
    ", solve_x() + solve_y()); 
    92     return 0; 
    93 } 

    下面是学长的QAQQ用了线段树维护

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define MN 10000
      4 #define MX 20000
      5 #define L (k << 1)
      6 #define R ((k << 1) + 1)
      7 using namespace std; 
      8 
      9 struct work{    //扫描线 
     10     int x, l, r, p; 
     11 }x[MN + 5], y[MN + 5];
     12 
     13 bool cmp(work a, work b){
     14     return a.x == b.x ? a.p > b.p : a.x < b.x; 
     15 }
     16 
     17 struct data{
     18     int x, s; 
     19 };
     20 
     21 data operator + (data a, data b){
     22     if (a.x == b.x) {
     23         return (data) {
     24             a.x, a.s + b.s
     25         };
     26     }
     27     return a.x < b.x ? a : b; 
     28 }
     29 
     30 struct node{
     31     int l, r, mk;
     32     data x;
     33 }t[MX * 4 + 5]; 
     34 
     35 inline void up (int k){
     36     t[k].x = t[L].x + t[R].x; 
     37 }
     38 
     39 inline void add(int k, int x){
     40     t[k].x.x += x; 
     41     t[k].mk += x; 
     42 }
     43 
     44 inline void down(int k){
     45     if (t[k].mk) {
     46         add(L, t[k].mk); 
     47         add(R, t[k].mk); 
     48         t[k].mk = 0; 
     49     }
     50 }
     51 
     52 void build(int k, int l, int r) {
     53     t[k].l = l; 
     54     t[k].r = r; 
     55     if (l == r) {
     56         t[k].x.s = 1; 
     57         return; 
     58     }
     59     int mid = l + r >> 1;  
     60     build(L, l, mid); 
     61     build(R, mid + 1, r); 
     62     up(k); 
     63 }
     64 
     65 void renew(int k, int l, int r, int x) {
     66     if (t[k].l == l && t[k].r == r) {
     67         add(k, x); 
     68         return; 
     69     }
     70     down(k); 
     71     int mid = t[k].l + t[k].r >> 1; 
     72     if (r <= mid) {
     73         renew(L, l, r, x); 
     74     }
     75     else if (l > mid) {
     76         renew(R, l, r, x); 
     77     }
     78     else {
     79         renew(L, l, mid, x); 
     80         renew(R, mid + 1, r, x); 
     81     }
     82     up(k); 
     83 }
     84 
     85 data query(int k, int l, int r){
     86     if (t[k].l == l && t[k].r == r) {
     87         return t[k].x; 
     88     }
     89     down(k); 
     90     int mid = (t[k].l + t[k].r) >> 1; 
     91     if (r <= mid) {
     92         return query(L, l, r); 
     93     }
     94     if (l > mid) {
     95         return query(R, l, r); 
     96     }
     97     return query(L, l, mid) + query(R, mid + 1, r); 
     98 }
     99 int n, ans; 
    100 void solve (work *x) {
    101     for (int i = 0; i < n; i++) {
    102         if (x[i].p < 0) {
    103             renew(1, x[i].l, x[i].r, -1); 
    104         }
    105         data d = query(1, x[i].l, x[i].r); 
    106         if (x[i].p > 0) {
    107             renew(1, x[i].l, x[i].r, 1); 
    108         }
    109         ans += d.x ? 0 : d.s; 
    110     }
    111 }
    112 
    113 int main(){
    114     int i, x0, y0, x1, y1; 
    115     scanf("%d", &n); 
    116     for (int i = 0; i < n; ++i) {
    117         scanf("%d%d%d%d", &x0, &y0, &x1, &y1); 
    118         x0 += MN; 
    119         y0 += MN; 
    120         x1 += MN; 
    121         y1 += MN; 
    122         x[i] = (work) {
    123             y0, x0, x1 - 1, 1
    124         }; 
    125         x[i + n] = (work) {
    126             y1, x0, x1 - 1, -1
    127         }; 
    128         y[i] = (work) {
    129             x0, y0, y1 - 1, 1
    130         }; 
    131         y[i + n] = (work) {
    132             x1, y0, y1 - 1, -1
    133         };
    134     }
    135     n <<= 1; 
    136     sort(x, x + n, cmp); 
    137     sort(y, y + n, cmp); 
    138     build(1, 0, MX); 
    139     solve(x); 
    140     solve(y); 
    141     printf("%d", ans); 
    142     return 0; 
    143 }


  • 相关阅读:
    mysql基本命令(转)
    查找大文件
    vim/vi 复制,删除,粘贴,查找,替换
    redhat 6用yum方式安装nginx
    解决yum安装时 Cannot retrieve repository metadata (repomd.xml) for repository
    RHEL6解决无法使用YUM源问题(转)
    Linux 信号概念
    Linux 进程通信(共享内存区)
    Linux 进程通信(有名管道)
    Linux 进程通信(无名管道)
  • 原文地址:https://www.cnblogs.com/GldHkkowo/p/8857297.html
Copyright © 2011-2022 走看看