题意 给你n个矩形 每个矩形都有自己的value 你可以任意改变矩形的表里关系 被覆盖的地方的value取最表层的 求总value的最大值
刚看了扫描线 感觉这个可以用扫描线做就直接写了 其实直接离散化就行了 因为最多也就20个矩形 那坐标最多也就40个 那我们对坐标进行离散化 然后将矩形按value从小到大一个个的放 暴力更新覆盖格子的value 最后直接将2n * 2n个小格子的value加起来就行了
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 50; int y[N], x[N], n, m; ll val[N][N]; struct Rect { int x1, y1, x2, y2, v; bool operator< (const Rect &r) const{ return v < r.v; } } r[N]; int fid(int a[], int k){ return lower_bound(a, a + m, k) - a; } int main() { int T, x1, y1, x2, y2, cas = 0; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = m = 0; i < n; ++i, m += 2) { scanf("%d%d%d%d%d", &r[i].x1, &r[i].y1, &r[i].x2, &r[i].y2, &r[i].v); x[m] = r[i].x1, x[m + 1] = r[i].x2; y[m] = r[i].y1, y[m + 1] = r[i].y2; } sort(r, r + n); //将value小的大楼放前面 sort(x, x + m); //离散化x sort(y, y + m); //离散化y memset(val, 0, sizeof(val)); for(int i = 0; i < n; ++i) { x1 = fid(x, r[i].x1), x2 = fid(x, r[i].x2); //获得x离散化后的坐标 y1 = fid(y, r[i].y1), y2 = fid(y, r[i].y2); //获得y离散化后的坐标 for(int j = x1; j < x2; ++j) for(int k = y1; k < y2; ++k) val[j][k] = r[i].v; } ll ans = 0; for(int i = 0; i < m - 1; ++i) for(int j = 0; j < m - 1; ++j) ans += val[i][j] * (x[i + 1] - x[i]) * (y[j + 1] - y[j]); printf("Case %d: %I64d\n", ++cas, ans); } return 0; }还有扫描线a的代码 用扫描线的时候是将矩形value从大到小排序 每放置一个矩形 看面积改变了多少 然后就用value乘以这个改变的面积
#include <cstdio> #include <cstring> #include <algorithm> #define lc p<<1, s, mid #define rc p<<1|1, mid+1, e #define mid ((s+e)>>1) using namespace std; typedef long long ll; const int N = 50; int y[N], flag[N * 2], len[N * 2]; struct Rect { int x1, y1, x2, y2, v; bool operator< (const Rect &r) const { return v > r.v; } } r[N]; struct SLine { int x, y1, y2, flag; SLine() {} SLine(int xx, int a, int b, int f): x(xx), y1(a), y2(b), flag(f) {} bool operator< (const SLine &s) const { return x < s.x; } } line[N]; void build() { memset(flag, 0, sizeof(flag)); memset(len, 0, sizeof(len)); } void pushup(int p, int s, int e) { if(flag[p]) len[p] = y[e] - y[s - 1]; else if(s == e) len[p] = 0; else len[p] = len[p << 1] + len[p << 1 | 1]; } void update(int p, int s, int e, int l, int r, int v) { if(l <= s && e <= r) { flag[p] += v; pushup(p, s, e); return; } if(l <= mid) update(lc, l, r, v); if(r > mid) update(rc, l, r, v); pushup(p, s, e); } int main() { int T, n, m, cas = 0; int x1, y1, x2, y2, v; ll ans; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 0; i < n; ++i) scanf("%d%d%d%d%d", &r[i].x1, &r[i].y1, &r[i].x2, &r[i].y2, &r[i].v); sort(r, r + n); ll ans = 0, last = 0, area; for(int i = m = 0; i < n; ++i) { build(); area = 0; y[m] = r[i].y1, y[m + 1] = r[i].y2; line[m++] = SLine(r[i].x1, r[i].y1, r[i].y2, 1); line[m++] = SLine(r[i].x2, r[i].y1, r[i].y2, -1); sort(y, y + m); sort(line, line + m); for(int j = 0; j < m - 1; ++j) { int l = lower_bound(y, y + m, line[j].y1) - y; int r = lower_bound(y, y + m, line[j].y2) - y; update(1, 1, m, l + 1, r, line[j].flag); area += len[1] * (line[j + 1].x - line[j].x); } ans += (area - last) * r[i].v; last = area; } printf("Case %d: %I64d\n", ++cas, ans); } return 0; }
1 3 1 1 10 10 4 4 4 15 5 5 7 8 20 30 6
Case 1: 2047
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/acvay/article/details/47656595