zoukankan      html  css  js  c++  java
  • hdu 4419 Colourful Rectangle (离散化扫描线线段树)

    Problem - 4419

      题意不难,红绿蓝三种颜色覆盖在平面上,不同颜色的区域相交会产生新的颜色,求每一种颜色的面积大小。

      比较明显,这题要从矩形面积并的方向出发。如果做过矩形面积并的题,用线段树做的,这题就只差一个把每个区域计算单独出来的思路了。

      这里不详细介绍扫描线,只是说一下针对这题的做法。其实网上有好多版本,都是直接单独计算答案的。然而,我稍微绕了个小弯,我觉得我这种处理方法也是比较容易想到以及实现的。如果我们用7棵线段树计算R、G、B、R||G、R||B、B||G、R||G||B这7种情况,我们并不能直接得到所要的答案。不过可以知道,ans(G)=S(R||G||B)-S(R||B)的(这里的||是两种颜色的面积并的意思)。同理我们可以得到ans(B)、ans(R)。然后根据这个,我们可以得到ans(RB)=S(R||G||B)-ans(R)-ans(B)-S(G)。同理可以得到ans(RG),ans(GB)。最后就只剩ans(RGB)了。

    代码如下:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <map>
      4 #include <iostream>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 
      9 map<char, int> id;
     10 void preMap() {
     11     id['R'] = 0;
     12     id['G'] = 1;
     13     id['B'] = 2;
     14 }
     15 
     16 const int N = 22222;
     17 const int K = 1 << 3;
     18 map<int, int> xid;
     19 int rx[N], xn;
     20 
     21 struct Node {
     22     int id, x1, x2, y;
     23     bool end;
     24     Node() {}
     25     Node(int id, int x1, int x2, int y, bool end)
     26         : id(id), x1(x1), x2(x2), y(y), end(end) {}
     27 } node[N];
     28 
     29 void input(int n) {
     30     char buf[3];
     31     int a, b, c, d;
     32     for (int i = 0; i < n; i++) {
     33         scanf("%s%d%d%d%d", buf, &a, &b, &c, &d);
     34         if (a > c) swap(a, c);
     35         if (b > d) swap(b, d);
     36         rx[i << 1] = a;
     37         rx[i << 1 | 1] = c;
     38         node[i << 1] = Node(id[buf[0]], a, c, b, false);
     39         node[i << 1 | 1] = Node(id[buf[0]], a, c, d, true);
     40     }
     41     n <<= 1;
     42     sort(rx, rx + n);
     43     xn = unique(rx, rx + n) - rx;
     44 //    for (int i = 0; i < xn; i++) cout << rx[i] << ' '; cout << endl;
     45     xid.clear();
     46     for (int i = 0; i < xn; i++) xid[rx[i]] = i;
     47     for (int i = 0; i < n; i++) {
     48         node[i].x1 = xid[node[i].x1];
     49         node[i].x2 = xid[node[i].x2];
     50     }
     51 }
     52 
     53 #define lson l, m, rt << 1
     54 #define rson m + 1, r, rt << 1 | 1
     55 #define root 0, xn - 1, 1
     56 
     57 int sum[K][N << 2];
     58 int mk[K][N << 2];
     59 int cur;
     60 
     61 void up(int rt, int l, int r) {
     62     if (mk[cur][rt]) sum[cur][rt] = rx[r + 1] - rx[l];
     63     else sum[cur][rt] = sum[cur][rt << 1] + sum[cur][rt << 1 | 1];
     64 }
     65 
     66 void build(int l, int r, int rt) {
     67     sum[cur][rt] = mk[cur][rt] = 0;
     68     if (l == r) return ;
     69     int m = l + r >> 1;
     70     build(lson);
     71     build(rson);
     72 }
     73 
     74 void update(int k, int L, int R, int l, int r, int rt) {
     75     if (L <= l && r <= R) {
     76         mk[cur][rt] += k;
     77         if (l != r) up(rt, l, r);
     78         else {
     79             if (mk[cur][rt]) sum[cur][rt] = rx[r + 1] - rx[l];
     80             else sum[cur][rt] = 0;
     81         }
     82         return ;
     83     }
     84     int m = l + r >> 1;
     85     if (L <= m) update(k, L, R, lson);
     86     if (m < R) update(k, L, R, rson);
     87     up(rt, l, r);
     88 }
     89 
     90 bool cmp(Node a, Node b) { return a.y < b.y || a.y == b.y && a.end < b.end;}
     91 
     92 typedef long long LL;
     93 
     94 void work(int n) {
     95     n <<= 1;
     96     LL tt[K];
     97     memset(tt, 0, sizeof(tt));
     98     sort(node, node + n, cmp);
     99     if (node[0].end) { puts("shit!!"); while (1) ;}
    100     for (cur = 0; cur < K; cur++) {
    101         build(root);
    102         if (cur & 1 << node[0].id) update(1, node[0].x1, node[0].x2 - 1, root);
    103     }
    104     for (int i = 1; i < n; i++) {
    105         for (cur = 0; cur < K; cur++) {
    106             if (sum[cur][1] < 0 || sum[cur][1] > 1e9) { puts("shit!!!"); while (1) ;}
    107             tt[cur] += (LL) sum[cur][1] * (node[i].y - node[i - 1].y);
    108             if (cur & (1 << node[i].id)) update(node[i].end ? -1 : 1, node[i].x1, node[i].x2 - 1, root);
    109         }
    110 //        for (int i = 0; i < K; i++) cout << tt[i] << ' '; cout << endl;
    111     }
    112     LL sgl[3], dbl[3], lst = tt[K - 1];
    113     for (int i = 0; i < 3; i++) {
    114         sgl[i] = tt[K - 1] - tt[(K - 1) ^ (1 << i)];
    115         lst -= sgl[i];
    116         cout << sgl[i] << endl;
    117     }
    118     for (int i = 0; i < 3; i++) {
    119         dbl[i] = tt[K - 1];
    120         for (int j = 0; j < 3; j++) {
    121             if (i != j) dbl[i] -= sgl[j];
    122             else dbl[i] -= tt[1 << j];
    123         }
    124         lst -= dbl[i];
    125     }
    126     for (int i = 2; i >= 0; i--) cout << dbl[i] << endl;
    127     cout << lst << endl;
    128 }
    129 
    130 int main() {
    131 //    freopen("in", "r", stdin);
    132     preMap();
    133     int T, n;
    134     scanf("%d", &T);
    135     for (int cas = 1; cas <= T; cas++) {
    136         scanf("%d", &n);
    137         input(n);
    138         printf("Case %d:
    ", cas);
    139         work(n);
    140     }
    141     return 0;
    142 }
    View Code

      感觉这种方法写起来不会吃力,就是计算上面会稍微需要思考。不过我还是因为把xid写成xd导致wa了一个晚上。_(囧」∠)_

    ——written by Lyon

  • 相关阅读:
    STM32+ESP8266+AIR202基本控制篇-301-服务器单向SSL认证-MQTT服务器配置SSL单向认证(.Windows系统)
    STM32+ESP8266+AIR202基本控制篇-213-功能测试-微信小程序扫码绑定Air302(NB-IOT),并通过MQTT和Air302(NB-IOT)实现远程通信控制
    17-STM32+ESP8266+AIR202基本控制篇-完成功能2-微信小程序使用APUConfig配网绑定ESP8266,并通过MQTT和ESP8266实现远程通信控制
    Python 元类
    硬核!15张图解Redis为什么这么快
    Protobuf 中 any 的妙用
    Grpc性能压测方法:用ghz进行压测
    压测工具Locuse的使用
    Locust 多机器分布式测试
    kubespray部署kubernetes高可用集群
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4419_Lyon.html
Copyright © 2011-2022 走看看