hdu1828, rectangle side length of the scanning line seek

This question is obtained by the scanning line perimeter of a rectangle, excluding the overlapping portion. You can sweep twice, once bristling sweep, sweep sideways once, twice sweep this bug I wrote here, now do not know where bug QAQ, or would like to forget a backhand sweep to write once.
Here Insert Picture Description
Paint simulate what the scan line scan process will find us sideways perimeter is added to each scan line changes after the tree line total length, and the bristling of the tree line and we maintain the covered section is relevant paragraphs, is set x segment, then this vertically perimeter = (the next scan line height - height which one scanning line) * x * 2. So we have to maintain the entire length of the interval after joining the scan lines, and the length of two or more pieces.
Talk about the maintenance of the number of segments, for an interval, we need to know he has a few paragraphs, it is necessary to know how many sections there are two sons, and the sons of mergers, may cause the two merged into a period, we maintain two each interval values fl, fr indicates that the left half of the range and there is whether or not accompanied portion has been covered, if the right part of the left son and right son of the left part is covered (see below) then the number of segments of the number of segments father's = son and - 1, so that the intermediate portion incorporates a small number of segments, otherwise = the number of segments and son. Finally, the answer is
Here Insert Picture Description

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod (10007)
#define middle (l+r)>>1
#define SIZE 1000000+5
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double ld;
const int inf_max = 0x3f3f3f;
const ll Linf = 9e18;
const int maxn = 2e4 + 5;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
    int f=1,res=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
    return f*res;
}
const int up = 100000 + 10;
struct node {
    int l,r,val,h;
    node(){};
    node(int x,int y,int z,int flag) {l = x;r = y;h = z;val = flag;}
}Line[maxn];
struct tnode {
    int flag,segnum,len,fl,fr;
}tree[up << 2];
int n,totx;
bool cmp(node a,node b) {
    return (a.h == b.h ? a.val > b.val : a.h < b.h);
}
void rst() {
    totx = 0;
    memset(tree,0,sizeof(tree));
}
void pushup(int rt,int l,int r) {
    if(tree[rt].flag) { //如果这一整段区间都被覆盖,那么就不用管儿子,直接自己更形
        tree[rt].len = r + 1 - l;
        tree[rt].fl = 1; tree[rt].fr = 1; tree[rt].segnum = 1;
    }else {
        tree[rt].len = tree[lson].len + tree[rson].len;
        tree[rt].segnum = tree[rson].segnum + tree[lson].segnum;
        if(tree[lson].fr == 1 && tree[rson].fl == 1) tree[rt].segnum--; //如何左儿子和右儿子中间部分可以合为一段
        tree[rt].fl = tree[lson].fl;tree[rt].fr = tree[rson].fr;
    }
}
void update(int rt,int l,int r,int ql,int qr,int f) {
    if(ql == l && qr == r) {
        tree[rt].flag += f;
        pushup(rt,l,r);
        return ;
    }
    int mid = middle;
    if(qr <= mid) update(lson,l,mid,ql,qr,f);
    else if(ql > mid) update(rson,mid + 1,r,ql,qr,f);
    else {
        update(lson,l,mid,ql,mid,f);
        update(rson,mid + 1,r,mid + 1,qr,f);
    }
    pushup(rt,l,r);
}
int main()
{
    while(~scanf("%d",&n)) {
        rst();
        for(int i = 1;i <= n; ++i) {
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            x1 += 10005,y1 += 10005,x2 += 10005,y2 += 10005; //省去离散化
            Line[++totx] = node(x1,x2,y1,1);
            Line[++totx] = node(x1,x2,y2,-1);
        }
        sort(Line + 1,Line + 1 + totx,cmp);
        int ans = 0,pre = 0;
        for(int i = 1;i <= totx; ++i) {
            update(1,1,up,Line[i].l,Line[i].r - 1,Line[i].val); //把点换成区间,所以右端点要-1;
            if(i != totx)
                ans += (2 * tree[1].segnum * (Line[i + 1].h - Line[i].h)); //计算竖着的
            ans += abs(pre - tree[1].len);//计算横着的
            pre = tree[1].len;
        }
        cout<<ans<<endl;
    }
    return 0;
}
Published 37 original articles · won praise 19 · views 6192

Guess you like

Origin blog.csdn.net/qq_44077455/article/details/104102176