我觉得要注意的几点
1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1]
2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个push_down
3 注意push_up 写法有点不一样,不过是可以改成一样的。
简单裸题*2
L - Atlantis HDU - 1542
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; const int maxn = 220; double v[maxn]; struct node { double l, r, h; int d; node(double l = 0, double r = 0, double h = 0, int d = 0) :l(l), r(r), h(h), d(d) {} }line[maxn]; bool cmp(node a, node b) { return a.h < b.h; } double sum[maxn * 8]; int lazy[maxn * 4]; void build(int id, int l, int r) { sum[id] = 0; lazy[id] = 0; if (l == r) return; int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); } void push_up(int id, int l, int r) { if (lazy[id]) sum[id] = v[r + 1] - v[l]; else sum[id] = sum[id << 1] + sum[id << 1 | 1]; } void update(int id, int l, int r, int x, int y, int d) { if (x <= l && y >= r) { lazy[id] += d; push_up(id, l, r); return; } int mid = (l + r) >> 1; if (x <= mid) update(id << 1, l, mid, x, y, d); if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, d); push_up(id, l, r); } int main() { int n, cas = 0; while (scanf("%d", &n) != EOF && n) { int cnt = 0, tot = 0; for (int i = 1; i <= n; i++) { double x1, y1, x2, y2; scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); v[++cnt] = x1, v[++cnt] = x2; line[++tot] = node(x1, x2, y1, 1), line[++tot] = node(x1, x2, y2, -1); } sort(v + 1, v + 1 + cnt); sort(line + 1, line + 1 + tot, cmp); int len = unique(v + 1, v + 1 + cnt) - v - 1; double ans = 0; build(1, 1, len - 1); for (int i = 1; i < tot; i++)//这里注意只需要要tot-1即可,因为我们每次都是按底算的 { int l = lower_bound(v + 1, v + 1 + len, line[i].l) - v; int r = lower_bound(v + 1, v + 1 + len, line[i].r) - v - 1; update(1, 1, len - 1, l, r, line[i].d); ans += sum[1] * (line[i + 1].h - line[i].h); } printf("Test case #%d ", ++cas); printf("Total explored area: %.2lf ", ans); } return 0; }
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; typedef long long ll; const int maxn = 8e4 + 10; ll v[maxn]; struct node { ll l, r, h; int d; node(ll l = 0, ll r = 0, ll h = 0, int d = 0) :l(l), r(r), h(h), d(d) {} }line[maxn]; bool cmp(node a, node b) { return a.h < b.h; } ll sum[maxn * 8]; int lazy[maxn * 4]; void build(int id, int l, int r) { sum[id] = 0; lazy[id] = 0; if (l == r) return; int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); } void push_up(int id, int l, int r) { if (lazy[id]) sum[id] = v[r + 1] - v[l]; else sum[id] = sum[id << 1] + sum[id << 1 | 1]; } void update(int id, int l, int r, int x, int y, int d) { if (y<l || x>r) return; // printf("id=%d l=%d r=%d x=%d y=%d ", id, l, r, x, y); if (x <= l && y >= r) { lazy[id] += d; if (lazy[id]) sum[id] = v[r + 1] - v[l]; else sum[id] = sum[id << 1] + sum[id << 1 | 1]; return; } int mid = (l + r) >> 1; if (x <= mid) update(id << 1, l, mid, x, y, d); if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, d); push_up(id, l, r); } int main() { int n, cnt = 0, tot = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) { ll l, r, h; scanf("%lld%lld%lld", &l, &r, &h); v[++cnt] = l, v[++cnt] = r; line[++tot] = node(l, r, 0, 1), line[++tot] = node(l, r, h, -1); } sort(v + 1, v + 1 + cnt); sort(line + 1, line + 1 + tot, cmp); int len = unique(v + 1, v + 1 + cnt) - v - 1; build(1, 1, len - 1); ll ans = 0; for (int i = 1; i < tot; i++) { int l = lower_bound(v + 1, v + 1 + len, line[i].l) - v; int r = lower_bound(v + 1, v + 1 + len, line[i].r) - v - 1; // printf("l=%d r=%d ", l, r); update(1, 1, len - 1, l, r, line[i].d); ans += sum[1] * (line[i + 1].h - line[i].h); // printf("%lld %lld ans=%lld %lld sum=%lld ", line[i].l, line[i].r, ans, line[i].h, sum[1]); // printf("%lld %lld ans=%lld %lld ", line[i + 1].l, line[i + 1].r, ans, line[i + 1].h); // printf(" "); } printf("%lld ", ans); return 0; }
然后就是一个没有这么简单的裸题,比较暴力。
这个是给每一个y轴都建一棵线段树,每一个y轴代表 y[L]~y[L+1]
然后每次对于这个矩形的每一个y轴的这一段都查一下,然后如果已经被覆盖了,就删去这一段,然后更新这一段。
这个题目其实还是很好写的,但是要注意push_down的写法。
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <cstring> using namespace std; const int maxn = 440; struct rect { int x1, y1, x2, y2, col; rect(int x1=0,int y1=0,int x2=0,int y2=0,int col=0):x1(x1),y1(y1),x2(x2),y2(y2),col(col){} }ex[maxn]; int vx[maxn * 2], vy[maxn * 2], color[maxn]; int sum[maxn][maxn * 8], lazy[maxn][maxn * 8]; void build(int i,int id,int l,int r) { sum[i][id] = lazy[i][id] = 0; if (l == r) return; int mid = (l + r) >> 1; build( i,id << 1, l, mid); build(i, id << 1 | 1, mid + 1, r); } void push_up(int i,int id) { sum[i][id] = sum[i][id << 1] + sum[i][id << 1 | 1]; // printf("sum[%d][%d]=%d ", i, id, sum[i][id]); } void push_down(int i,int id,int l,int r) { if (lazy[i][id] == 0) return; int mid = (l + r) >> 1; sum[i][id << 1] = vx[mid + 1] - vx[l]; sum[i][id << 1 | 1] = vx[r + 1] - vx[mid + 1]; lazy[i][id << 1] = lazy[i][id << 1 | 1] = lazy[i][id]; // printf("l=%d r=%d mid=%d ", l, r, mid); // printf("x sum[%d][%d]=%d ", i, id<<1, sum[i][id<<1]); // printf("x sum[%d][%d]=%d ", i, id<<1|1, sum[i][id<<1|1]); lazy[i][id] = 0; } void update(int i,int id,int l,int r,int x,int y) { if (x <= l && y >= r) { sum[i][id] = vx[r + 1] - vx[l]; // printf("l=%d r=%d ", l, r); // printf("ww sum[%d][%d]=%d ", i, id, sum[i][id]); lazy[i][id] = 1; return; } int mid = (l + r) >> 1; push_down(i, id, l, r); if (x <= mid) update(i, id << 1, l, mid, x, y); if (y > mid) update(i, id << 1 | 1, mid + 1, r, x, y); push_up(i, id); } int query(int i,int id,int l,int r,int x,int y) { if (x <= l && y >= r) return sum[i][id]; int mid = (l + r) >> 1, ans = 0; push_down(i, id, l, r); if (x <= mid) ans += query(i, id << 1, l, mid, x, y); if (y > mid) ans += query(i, id << 1 | 1, mid + 1, r, x, y); return ans; } int main() { int w, h, n, cas = 0; while (scanf("%d%d", &w, &h) && (w + h)) { memset(color, 0, sizeof(color)); int tot = 0, cnt = 0; scanf("%d", &n); vx[++tot] = 0, vx[++tot] = w; vy[++cnt] = 0, vy[++cnt] = h; for (int i = 1; i <= n; i++) { int x1, y1, x2, y2, col; scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &col); ex[i] = rect(x1, y1, x2, y2, col); vx[++tot] = x1, vx[++tot] = x2; vy[++cnt] = y1, vy[++cnt] = y2; } sort(vx + 1, vx + 1 + tot); sort(vy + 1, vy + 1 + cnt); int lenx = unique(vx + 1, vx + 1 + tot) - vx - 1; int leny = unique(vy + 1, vy + 1 + cnt) - vy - 1; // for (int i = 1; i <= lenx; i++) printf("vx[%d]=%d ", i, vx[i]); for (int i = 1; i < leny; i++) build(i, 1, 1, lenx - 1); for (int i = n; i >= 1; i--) { // printf("i=%d ", i); int col = ex[i].col; int ans = (ex[i].x2 - ex[i].x1)*(ex[i].y2 - ex[i].y1); int lx = lower_bound(vx + 1, vx + 1 + lenx, ex[i].x1) - vx; int ly = lower_bound(vy + 1, vy + 1 + leny, ex[i].y1) - vy; int rx = lower_bound(vx + 1, vx + 1 + lenx, ex[i].x2) - vx - 1; int ry = lower_bound(vy + 1, vy + 1 + leny, ex[i].y2) - vy - 1; for (int j = ly; j <= ry; j++) { int res = query(j, 1, 1, lenx - 1, lx, rx); ans -= (vy[j + 1] - vy[j])*res; // printf("j=%d ", j); // printf("lx=%d ly=%d rx=%d ry=%d ", lx, ly, rx, ry); // printf("x1=%d y1=%d x2=%d y2=%d ", ex[i].x1, ex[i].y1, ex[i].x2, ex[i].y2); // printf("res=%d %d ans=%d ", res, vy[j + 1] - vy[j],ans); update(j, 1, 1, lenx - 1, lx, rx); } color[col] += ans; // printf("color[%d]=%d ", col, color[col]); // printf(" "); } int num = 0; if (cas) printf(" "); printf("Case %d: ", ++cas); for (int i = 1; i <= 100; i++) { if (color[i]) { printf("%d %d ", i, color[i]); num++; } } if (num == 1) printf("There is %d color left on the wall. ", num); else printf("There are %d colors left on the wall. ", num); } return 0; } /* 10 8 4 1 9 5 10 9 1 8 2 9 8 7 1 10 8 4 6 2 9 6 4 0 0 */