P1856 [USACO5.5】画像の矩形外周[走査線】

トピックの背景

同じ形状のポスター、写真の多くに近い壁。その辺は、水平および垂直です。各長方形の画像は他の画像の一部または全部を覆うことができます。長方形の周囲の全ての後に合成エッジ長さと呼ばれます。

タイトル説明

周囲を計算するプログラムを書きます。

IMG

1図7の長方形に示します。

IMG

図2は、全ての境界矩形に示すように。長方形のすべての頂点の座標は整数です。


解決

シミュレーションの最初と思うが、この小さな問題データ、転換点を掃引直接暴力、増分統計周囲はする必要があります。

実際には、最適な解決策は、そうすることです。

タグの走査線があり、の行をスキャンすることを使用してみましょう。

簡単に言えば、アイデアは(具体的な実現は、Baiduは、私が書くのが面倒だことができます)カバーセグメントをやって、まだ同じ走査線です。+1のエッジ重み値、左から右に再び掃引再び下から上に掃引-1のエッジ重み値、、、それがエッジ検出したとき、現在の走査線と上部カバーセグメント長との統計を増分は、具体的には、この増分の違いを行うことです。

正しさの単純な証明は:側によって引き起こされる上記各増分については、その後の増分は、最終的にエッジによって相殺されます。だから我々は唯一のインクリメンタル側を数える場合、それは二回、常に長方形の周囲で発生します。実際には、非常に欠場。

参照コード

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 20010
#define MOD 2520
#define E 1e-12
using namespace std;
inline int read()
{
    int f=1,x=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
struct node{
    int l,r,h,v;
    bool operator<(const node &a)const{
        if(a.h==h) return a.v<v;
        return a.h>h;
    }
}h[N],l[N];
struct tree{
    int l,r;
    int cnt,dat;
}t[N<<2];
int n,hh[N],hl[N],cmd;
inline void pushup(int p)//线段覆盖
{
    if(t[p].cnt){
        if(cmd==1) t[p].dat=hh[t[p].r+1]-hh[t[p].l];
        else t[p].dat=hl[t[p].r+1]-hl[t[p].l];
    }
    else if(t[p].l==t[p].r) t[p].dat=0;
    else t[p].dat=t[p<<1].dat+t[p<<1|1].dat;
}
inline void build(int p,int l,int r)
{
    t[p].l=l,t[p].r=r;
    t[p].cnt=t[p].dat=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
}
inline void change(int p,int l,int r,int val)
{
    if(l<=t[p].l&&t[p].r<=r){
        t[p].cnt+=val;
        pushup(p);
        return;
    }
    int mid=(t[p].l+t[p].r)>>1;
    if(l<=mid) change(p<<1,l,r,val);
    if(r>mid) change(p<<1|1,l,r,val);
    pushup(p);
}
int main()
{
    n=read();
    int cnth=0,cntl=0,th=0,tl=0;
    for(int i=1;i<=n;++i){
        int x1,x2,y1,y2;
        x1=read(),y1=read(),x2=read(),y2=read();
        h[++cnth].l=x1,h[cnth].r=x2,h[cnth].h=y1,h[cnth].v=1;
        l[++cntl].l=y1,l[cntl].r=y2,l[cntl].h=x1,l[cntl].v=1;
        h[++cnth].l=x1,h[cnth].r=x2,h[cnth].h=y2,h[cnth].v=-1;
        l[++cntl].l=y1,l[cntl].r=y2,l[cntl].h=x2,l[cntl].v=-1;
        hh[++th]=x1,hh[++th]=x2;
        hl[++tl]=y1,hl[++tl]=y2;
    }
    sort(hh+1,hh+th+1);sort(hl+1,hl+tl+1);
    sort(h+1,h+cnth+1);sort(l+1,l+cntl+1);
    unique(hh+1,hh+th+1);unique(hl+1,hl+tl+1);
    int ans=0,tmp=0;
    build(1,1,cnth);
    cmd=1;
    for(int i=1;i<=cnth;++i){
        int x,y;
        x=lower_bound(hh+1,hh+th+1,h[i].l)-hh;
        y=lower_bound(hh+1,hh+th+1,h[i].r)-hh-1;
        change(1,x,y,h[i].v);
        if(h[i].v==1)ans+=t[1].dat-tmp;
        tmp=t[1].dat;
    }
    build(1,1,cntl);
    cmd=2,tmp=0;
    for(int i=1;i<=cntl;++i){
        int x,y;
        x=lower_bound(hl+1,hl+tl+1,l[i].l)-hl;
        y=lower_bound(hl+1,hl+tl+1,l[i].r)-hl-1;
        change(1,x,y,l[i].v);
        if(l[i].v==1)ans+=t[1].dat-tmp;
        tmp=t[1].dat;
    }
    ans<<=1;
    cout<<ans<<endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/DarkValkyrie/p/11565289.html