Study notes - the scanning lines

The main scanning line is the first step to sort scanned for one dimension, and data structures maintained by the contribution arising from the current scan line. (Generally used discrete segment tree +)

Matrices with today perimeter and area on a plane and scanning lines, and to talk.

 

POJ1151 - Atlantis (matrix and area)

We consider for $ y $ axis from the first scan, each time to see the rest of the bottom multiplied by the height of this update, so that you can

Let sorted by $ y $ axis, then for $ x $ axis discrete, with a segment tree $ cnt $ preservation is completely covered several times during this interval, $ sum $ store the remaining bottom within this range length.

When scanning, we classify the current side is the upper side or lower side, if the upper edge on the rest of the range is covered, then the lower edge deletion (ie the opposite of updates), and then began to count the answer to the second scan lines

Note: In the code to achieve, in fact modify the interval did not need to write $ pushdown $ function, always check because the query is $ sum [1] $, and modify the operation, must be in pairs, do not need the above information processing to below.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const double inf=2e9;
const int N=102000;

int n;
struct Point{
    double x1,y1,x2,y2;
}a[N];

struct Line{
    double y;
    int flag,id;//flag=1:下位边  flag=-1:上位边 
    bool operator < (const& RHS Line) const {
         return Y < rhs.y; 
    } 
    Line () {} 
    Line ( Double Y, int In Flag, int ID): Y (Y), In Flag (In Flag), ID (ID) {} 
} Li [N * 2 ]; 

Double T [N * 2 ], SUM [N * . 8 ];
 int CNT [N * . 8 ]; // there are 2 * n points 
int V [N * 2 ];
 // do not have access interval, not need pushdown 
void push_up ( int X, int L, int R & lt) 
{ 
    IF(CNT [X]) SUM [X] = T [R & lt + . 1 ] - T [L];
     the else  IF (L == R & lt) SUM [X] = 0 ;
     the else SUM [X] = SUM [X + X] + SUM [X + X + . 1 ]; 
} 

void Update ( int X, int L, int R & lt, int L, int R & lt, int UPD) 
{ 
    IF (L> R & lt) return ;
     IF (L <= L && R & lt <= R & lt) 
    { 
        CNT [X] + = UPD; 
        push_up (X, L, R & lt); // SUM before update directly, without considering the two cases 0 or 1 
        return  ;
    }
    int mid=(l+r)>>1;
    if(mid>=L) update(x+x,l,mid,L,R,upd);
    if(mid<R) update(x+x+1,mid+1,r,L,R,upd);
    push_up(x,l,r);
}

void build(int x,int l,int r)
{
    if(l==r) 
    {
        sum[x]=0; cnt[x]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(x+x,l,mid);
    build(x+x+1,mid+1,r);
}

void printans(double ans,int tot)
{
    printf("Test case #%d\nTotal explored area: %.2f\n\n",tot,ans);
}

int tot=0;
int main()
{
    while(scanf("%d",&n)!=EOF&&n)
    {
        double ans=0; tot++;
        for(int i=1;i<=n;i++) 
        {
            scanf("%lf%lf%lf%lf",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
            t[i*2-1]=a[i].x1; t[i*2]=a[i].x2;
            li[i*2-1]=Line(a[i].y1,1,i);
            li[i*2]=Line(a[i].y2,-1,i);
        }
        sort(t+1,t+2*n+1);
        sort(li+1,li+2*n+1);
        int m=unique(t+1,t+n+n+1)-t-1;
        for(int i=1;i<=n;i++)
        {
            a[i].x1=lower_bound(t+1,t+m+1,a[i].x1)-t;
            a[i].x2=lower_bound(t+1,t+m+1,a[i].x2)-t;
        }
        build(1,1,m-1);
        for(int i=1;i<=2*n;i++)
        {
            if(i>1&&li[i].y>li[i-1].y)
            {
                double delta=li[i].y-li[i-1].y;
                ans+=delta*sum[1];
            }
            update(1,1,m-1,a[li[i].id].x1,a[li[i].id].x2-1,li[i].flag);
            //segtree里的i代表i~i+1区间 
        }
        printans(ans,tot);
    }
    return 0;
}

 

Luo Valley P1856 - [USACO5.5] Picture rectangular perimeter (perimeter and rectangle)

The idea is similar to, but different approaches.

We still consider the contribution of the answer to the time of the search each scan line, on the lower side will be affected.

So we each scan line, before and after the insertion of the line have a query, the difference between the two remaining length of the interval is the contribution of the scan lines generated.

Because there is a horizontal line vertical line, so we are for $ x, y $ two rounds of scanning can be friends ~ ~ (This question is not discrete Yo ~)

Precautions: two scanning lines may be overlapped, which had no influence upon the matrix area, but will have an impact in terms of circumference. (As a possible rectangular upper side and a lower side of the rectangle coincides order if we do not sweep the upper side of the head, it will delete the original cover section, resulting in different states before and after the answer update; sweep another at the same height rectangular lower edge of time and because the range is deleted, and then covered with an updated answer would have been no coincidence upper and lower sides of the contribution, but here we had two contributions, so to improve it)

We also record it is the upper or lower side edge when the scanning lines are sorted, as a second key, the lower edge of the top face on it

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=102000;

int n;
struct segtree{
    int cnt,sum;
}tree[N*8];
struct node{
    int x1,y1,x2,y2;
}a[N];
struct Line{
    int val,flag;
    int lz,rz;
    Line(){
    }
    Line(int val,int flag,int lz,int rz):val(val),flag(flag),lz(lz),rz(rz){
    }
    bool operator < (const Line &rhs) const{
        if(val!=rhs.val) return val<rhs.val;
        return flag>rhs.flag;
    }
}X[2*N],Y[2*N];

void build(int x,int l,int r)
{
    if(l==r)
    {
        tree[x].cnt=tree[x].sum=0;
        return;
    }
    int mid=l+r>>1;
    build(x+x,l,mid);
    build(x+x+1,mid+1,r);
}

void pushup(int x,int l,int r)
{
    if(tree[x].cnt) tree[x].sum=r-l+1;//之前没+1 
    else tree[x].sum=tree[x+x].sum+tree[x+x+1].sum;
}

void update(int x,int l,int r,int L,int R,int upd)
{
    if(L>R) return;
    if(L<=l&&r<=R)
    {
        tree[x].cnt+=upd;
        pushup(x,l,r);
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=L) update(x+x,l,mid,L,R,upd);
    if(mid<R) update(x+x+1,mid+1,r,L,R,upd);
    pushup(x,l,r);
}

int _abs(int x)
{
    if(x<0) x=-x; return x;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
    {
        scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
        a[i].x1+=N; a[i].x2+=N; a[i].y1+=N; a[i].y2+=N;
        X[i*2-1]=Line(a[i].x1,1,a[i].y1,a[i].y2);
        X[i*2]=Line(a[i].x2,-1,a[i].y1,a[i].y2);//heng
        Y[i*2-1]=Line(a[i].y1,1,a[i].x1,a[i].x2);
        Y[i*2]=Line(a[i].y2,-1,a[i].x1,a[i].x2);//shu
    }
    int ans=0;
    int m=N+N;
    build(1,1,m);
    sort(X+1,X+n+n+1);
    for(int i=1;i<=n+n;i++)
    {
        int last=tree[1].sum;
        update(1,1,m,X[i].lz,X[i].rz-1,X[i].flag);//区间!要rz-1 
        int now=tree[1].sum;
        ans+=_abs(now-last);
    }
    build(1,1,m);
    sort(Y+1,Y+n+n+1);
    for(int i=1;i<=n+n;i++)
    {
        int last=tree[1].sum;
        update(1,1,m,Y[i].lz,Y[i].rz-1,Y[i].flag);//区间!要rz-1 
        int now=tree[1].sum;
        ans+=_abs(now-last);
    }
    cout<<ans<<endl;
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/Forever-666/p/11330097.html