这几天线段树学习中,但是扫描线这一段一直没写出代码来 努力了好几天终于可以了
这里是写扫描线代码需要注意的地方:
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就够了