Get The Treasury HDU - 3642 (扫描线求体积并)

题意:给你n个长方体,求至少相交三次的体积。

思路:1、z的数量较小,可以枚举z,对于两个z之间的夹层用二维扫描线

     2、对于每个夹层,用二维扫描线求出相交至少三次的面积和,最后乘上一个△z(夹层的高度)即可

易错点:(我的天,第一次写完好多bug,都是处理不当导致的,以后一定要避免了!)

  1、各个数组的下标要么全都是从0开始,要么都是从1开始,我比较喜欢从1开始。

  2、unique函数使用的时候后面减掉的是(数组的首地址 + 1),lower_bound函数减掉的是数组的首地址;因为unique获得的是数组元素的个数,而lower_bound获得的是元素的下标。(这些一定要记清楚了,以后写代码可以加快速度)

代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int maxn = 4010;
  5 int z[maxn];
  6 int x[maxn];
  7 
  8 struct point
  9 {
 10     int x, y, z;
 11     point(int a = 0, int b = 0, int c = 0) : x(a), y(b), z(c){}
 12 };
 13 struct cube
 14 {
 15     point a, b;
 16 }c[maxn];
 17 struct edge
 18 {
 19     int x1, x2;
 20     int y;
 21     int flag;
 22     edge(int a = 0, int b = 0, int c = 0, int d = 0) : x1(a), x2(b), y(c), flag(d){}
 23     bool operator< (const edge& b)const
 24     {
 25         return y < b.y;
 26     }
 27 }e[maxn];
 28 
 29 struct node
 30 {
 31     int l, r;
 32     int s;
 33     int len1, len2, len3;
 34 }t[maxn << 2];
 35 
 36 void pushup(int tar)
 37 {
 38     if (t[tar].s)
 39         t[tar].len1 = x[t[tar].r + 1] - x[t[tar].l];
 40     else if (t[tar].l == t[tar].r)
 41         t[tar].len1 = 0;
 42     else t[tar].len1 = t[tar << 1].len1 + t[tar << 1 | 1].len1;
 43 
 44     if (t[tar].s >= 2)
 45         t[tar].len2 = x[t[tar].r + 1] - x[t[tar].l];
 46     else if (t[tar].l == t[tar].r)
 47         t[tar].len2 = 0;
 48     else if (t[tar].s == 1)
 49         t[tar].len2 = t[tar << 1].len1 + t[tar << 1 | 1].len1;
 50     else t[tar].len2 = t[tar << 1].len2 + t[tar << 1 | 1].len2;
 51 
 52     if (t[tar].s >= 3)
 53         t[tar].len3 = x[t[tar].r + 1] - x[t[tar].l];
 54     else if (t[tar].l == t[tar].r)
 55         t[tar].len3 = 0;
 56     else if (t[tar].s == 2)
 57         t[tar].len3 = t[tar << 1].len1 + t[tar << 1 | 1].len1;
 58     else if (t[tar].s == 1)
 59         t[tar].len3 = t[tar << 1].len2 + t[tar << 1 | 1].len2;
 60     else t[tar].len3 = t[tar << 1].len3 + t[tar << 1 | 1].len3;
 61 }
 62 
 63 void build(int l, int r, int tar)
 64 {
 65     t[tar].l = l, t[tar].r = r, t[tar].s = t[tar].len1 = t[tar].len2 = t[tar].len3 = 0;
 66     if (l == r) return;
 67     int mid = (l + r) >> 1;
 68     build(l, mid, tar << 1), build(mid + 1, r, tar << 1 | 1);
 69 }
 70 
 71 void update(int l, int r, int v, int tar)
 72 {
 73     if (t[tar].l == l && t[tar].r == r)
 74     {
 75         t[tar].s += v;
 76         pushup(tar);
 77         return;
 78     }
 79     int mid = (t[tar].l + t[tar].r) >> 1;
 80     if (r <= mid) update(l, r, v, tar << 1);
 81     else if (l > mid) update(l, r, v, tar << 1 | 1);
 82     else update(l, mid, v, tar << 1), update(mid + 1, r, v, tar << 1 | 1);
 83     pushup(tar);
 84 }
 85 
 86 int main()
 87 {
 88     int T; cin >> T;
 89     int cases = 0;
 90     while (T--)
 91     {
 92         int n; cin >> n;
 93         int numz = 0, numx = 0;
 94         int nume = 0;
 95 
 96         for (int i = 1; i <= n; i++)
 97         {
 98             scanf("%d%d%d%d%d%d", &c[i].a.x, &c[i].a.y, &c[i].a.z, &c[i].b.x, &c[i].b.y, &c[i].b.z);
 99             z[++numz] = c[i].a.z, z[++numz] = c[i].b.z;
100         }
101         sort(z + 1, z + 1 + numz);
102         numz = unique(z + 1, z + 1 + numz) - z - 1;
103         ll res = 0;
104         for (int i = 1; i < numz; i++)
105         {
106             nume = numx = 0;
107             for (int j = 1; j <= n; j++)
108                 if (c[j].a.z <= z[i] && c[j].b.z > z[i])
109                 {
110                     e[++nume] = edge(c[j].a.x, c[j].b.x, c[j].a.y, 1);
111                     e[++nume] = edge(c[j].a.x, c[j].b.x, c[j].b.y, -1);
112                     x[++numx] = c[j].a.x, x[++numx] = c[j].b.x;
113                 }
114             sort(x + 1, x + 1 + numx);
115             numx = unique(x + 1, x + 1 + numx) - x - 1;
116             build(1, numx - 1, 1);
117             sort(e + 1, e + 1 + nume);
118             ll res1 = 0;
119             for (int j = 1; j < nume; j++)
120             {
121                 int x1, x2;
122                 x1 = lower_bound(x + 1, x + 1 + numx, e[j].x1) - x;
123                 x2 = lower_bound(x + 1, x + 1 + numx, e[j].x2) - x;
124                 update(x1, x2 - 1, e[j].flag, 1);
125                 res1 += (long long)t[1].len3 * (e[j + 1].y - e[j].y);
126             }
127             res += res1 * (z[i + 1] - z[i]);
128         }
129         printf("Case %d: %lld\n", ++cases, res);
130     }
131 }

 

转载于:https://www.cnblogs.com/liuwenhan/p/11611453.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值