线段树扫描线 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就够了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章