線段樹掃描線 hdu1542 Atlantis

這幾天線段樹學習中,但是掃描線這一段一直沒寫出代碼來 努力了好幾天終於可以了

這裏是寫掃描線代碼需要注意的地方:

1.每次插入一條線段的時候 只有當該線段和該節點表示的線段恰好相等的時候,纔對mark標記一下,即使是區間包含插入的線段也要向下推。

2.不需要延遲標記,因爲你插入了一條線段以後一定會完完全全的刪除 

3.每次更新的時候 ,先找到最底下一層(也就是插入線段和節點所管理的線段正好相等的時候) ,然後我們可以保證最底下一層是正確的,然後依次往上更新,用下面的正確信息去更新最上面的!

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <ctype.h>
#include <string.h>
#include <string>
using namespace std;
const int maxn=1000;
struct seg{
    double l,r,op,h;
    seg() {};
    seg(double x1,double x2,double x3,double x4) :l(x1),r(x2),h(x3),op(x4) {};
    bool operator < (const seg &a) const {return h<a.h;}
} T[maxn];
int mark[4*maxn+10];
vector<double> hashh;
double sum[(4*maxn)+10];
double x11,y11,x22,y22;//左上和右下
int n;
int getid(double x) {return (int)(lower_bound(hashh.begin(),hashh.end(),x)-hashh.begin());}
void update(int l,int r,int num,int left,int right,int op)
{
    if(l==left&&right==r) {
        mark[num]+=op;
        if(mark[num]) sum[num]=hashh[r+1]-hashh[l];
        else if(l==r) sum[num]=0;
        else sum[num]=sum[2*num]+sum[2*num+1];
        return ;
    }
    int mid=(left+right)/2;
    if(r<=mid) update(l,r,2*num,left,mid,op);
    else if(l>mid) update(l,r,2*num+1,mid+1,r,op);
    else update(l,mid,2*num,left,mid,op),update(mid+1,r,2*num+1,mid+1,right,op);
    
    if(mark[num]) sum[num]=hashh[right+1]-hashh[left];
    else sum[num]=sum[2*num]+sum[2*num+1];
}
int cmp(double a,double b) {return a<b;}


int main()
{
    int cpt=1;
    while(cin>>n&&n)
    {
        memset(sum,0,sizeof(sum));
        memset(mark,0,sizeof(mark));
        hashh.clear();
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            cin>>x11>>y11>>x22>>y22;
            T[cnt++]=seg(x11,x22,y22,-1);
            T[cnt++]=seg(x11,x22,y11,1);
            hashh.push_back(x11);
            hashh.push_back(x22);
        }//input
        sort(hashh.begin(),hashh.end(),cmp),unique(hashh.begin(),hashh.end());
        sort(T,T+cnt);//有cnt個線段 cnt個點 對 lim建立一個從一開始的線段樹 此過程不需要任何動作
        double s=0;
        int lim=(int)hashh.size();
        for(int i=0;i<cnt-1;i++)
        {
            double left=T[i].l,right=T[i].r;int op=T[i].op;int l=getid(left);int r=getid(right)-1;
            //cout<<l<<' '<<r<<'!'<<endl;
            update(l,r,1,0,lim-1,op);
            double dh=T[i+1].h-T[i].h;
            //cout<<sum[1]<<' '<<dh<<endl;
            s+=sum[1]*dh;
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",cpt++,s);
    }
    return 0;
}

代碼如上 一個udpate就夠了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章