HDU 1828 Picture(线段树 + 扫描线)

来源:互联网 发布:税控发票软件 编辑:程序博客网 时间:2024/06/01 09:59

题目链接:点击打开链接

题意:求n个矩形的周长的并。

思路:用扫描线法, 按照x坐标和y坐标分别扫描, 用线段树维护区间覆盖情况, yy了一下, 可以发现, 每次的可见轮廓都等于这次的区间覆盖长度和上一次的差值。

细节参见代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;typedef long long ll;typedef long double ld;const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;const int mod = 1000000000 + 7;const int INF = 0x3f3f3f3f;// & 0x7FFFFFFFconst int seed = 131;const ll INF64 = ll(1e18);const int maxn = 20000 + 10;int T,n,m,kase=0,addv[maxn<<2],sum[maxn<<2];struct edge {    int xl, yl, xr, yr;}a[6000];struct node {    int xl, xr, h, id;    node(int xl=0, int xr=0, int h=0, int id=0):xl(xl),xr(xr),h(h),id(id) {}    bool operator < (const node& rhs) const {        if(h == rhs.h) return id > rhs.id; //注意, 这里一定要这样排序, 比如数据: 2   0 0 4 4   0 4 4 8        else return h < rhs.h;    }}x[maxn],y[maxn];void PushUp(int l, int r, int o) {    if(addv[o]) sum[o] = r+1 - l;  //当前区间被线段覆盖    else if(l == r) sum[o] = 0; // 已经到了叶子结点且没有被覆盖    else sum[o] = sum[o<<1] + sum[o<<1|1]; // 没有完全被覆盖, 但是还没到叶子结点, 从其子区间中获得信息}void build(int l, int r, int o) {    int m = (l + r) >> 1;    addv[o] = sum[o] = 0;    if(l == r) return ;    build(l, m, o<<1);    build(m+1, r, o<<1|1);}void update(int L, int R, int x, int l, int r, int o) {    int m = (l + r) >> 1;    if(L <= l && r <= R) {        addv[o] += x;        PushUp(l, r, o);        return ;    }    if(L <= m) update(L, R, x, l, m, o<<1);    if(m < R) update(L, R, x, m+1, r, o<<1|1);    PushUp(l, r, o);}int xl, xr, yl, yr;int main() {    while(~scanf("%d",&n)) {        int cnt = 0, res = 0;        int mx = -INF, my = -INF;        for(int i=1;i<=n;i++) {            scanf("%d%d%d%d",&xl,&yl,&xr,&yr);            xl += 10001; xr += 10001;            yl += 10001; yr += 10001;            if(xl > xr) swap(xl, xr);            if(yl > yr) swap(yl, yr);            x[cnt++] = node(xl, xr, yr, -1);            x[cnt++] = node(xl, xr, yl, 1);            y[res++] = node(yl, yr, xl, 1);            y[res++] = node(yl, yr, xr, -1);            mx = max(mx, xr);            my = max(my, yr);        }        sort(x, x+cnt);        sort(y, y+res);        build(1, mx, 1);        int cur = 0;        ll ans = 0;        for(int i=0;i<cnt;i++) {            if(x[i].xl < x[i].xr) update(x[i].xl, x[i].xr-1, x[i].id, 1, mx, 1);            ans += abs(sum[1] - cur);            cur = sum[1];        }        cur = 0;        build(1, my, 1);        for(int i=0;i<res;i++) {            if(y[i].xl < y[i].xr) update(y[i].xl, y[i].xr-1, y[i].id, 1, my, 1);            ans += abs(sum[1] - cur);            cur = sum[1];        }        printf("%I64d\n",ans);    }    return 0;}


0 0