[USACO5.5]矩形周長Picture[掃描線+線段樹]
阿新 • • 發佈:2018-12-28
inline print operator sta ans 左右 -c con new
題意:給出一些矩陣,求這些矩陣合並後外部(被包括在內部的不算)周長
端點-1這個是用點代替了邊,區間內有幾個點就代表區間長度是多少
#include <bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; inline void chmax(int &x, int y) {if (x < y) x = y;} inline void chmin(int &x, int y) {if (x > y) x = y;} int Max = -inf, Min = inf, n, m, tot, ans, lastlen, x, y, xx, yy; struct Edge { int l, r, h, v; inline bool operator < (const Edge & rhs) const { return h == rhs.h ? v > rhs.v : h < rhs.h; } } G[10005]; inline void add(int l, int r, int h, int v) { G[++tot] = (Edge) {l, r, h, v}; } struct Node { int sum, cnt, len; //sum區間整體覆蓋次數,cnt有幾條不相交的線段覆蓋了這個區間 //len區間內被覆蓋的長度 bool rcvd, lcvd;//左右端點是否被覆蓋 Node *ls, *rs; inline void pushup(int l, int r) { if (sum) cnt = 1, len = r-l+1, lcvd = rcvd = 1; else if (l == r) len = 0, cnt = 0, lcvd = rcvd = 0;//Attention else { len = ls->len + rs->len; cnt = ls->cnt + rs->cnt; if (ls->rcvd && rs->lcvd) --cnt; lcvd = ls->lcvd; rcvd = rs->rcvd; } } } pool[100005], *root; void add(Node *cur, int l, int r, int ql, int qr, int v) { if (ql <= l && r <= qr) return cur->sum += v, cur->pushup(l, r); int mid = l+r>>1; if (ql <= mid) add(cur->ls, l, mid, ql, qr, v); if (qr > mid) add(cur->rs, mid+1, r, ql, qr, v); cur->pushup(l, r); } inline Node *newNode() { static int cnt = 0; return &(pool[cnt++]); } Node *build(int l, int r) { Node *cur = newNode(); if (l == r) return cur; int mid = l+r>>1; cur->ls = build(l, mid), cur->rs = build(mid+1, r); return cur; } int main(void) { scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%d%d%d%d", &x, &y, &xx, &yy); chmax(Max, xx), chmin(Min, x), add(x, xx, y, 1), add(x, xx, yy, -1); } if (Min <= 0) {//把坐標轉為正數,其實直接加上10001(本題坐標最大值)也是可以的 for(int i = 1; i <= tot; ++i) G[i].l += -Min+1, G[i].r += -Min+1; Max -= Min; } root = build(1, Max); sort(G+1, G+1+tot); for(int i = 1; i <= tot; ++i) { add(root, 1, Max, G[i].l, G[i].r-1, G[i].v);//不是很懂為什麽要-1,這奇怪的方式 while(G[i].h==G[i+1].h&&G[i].v==G[i+1].v) {//防止多次統計答案 ++i; add(root, 1, Max, G[i].l, G[i].r-1, G[i].v); } ans += abs(root->len-lastlen);//統計橫邊長度 lastlen = root->len; ans += root->cnt*2*(G[i+1].h-G[i].h);//統計豎邊長度 } printf("%d\n", ans); return 0; }
[USACO5.5]矩形周長Picture[掃描線+線段樹]