這幾天線段樹學習中,但是掃描線這一段一直沒寫出代碼來 努力了好幾天終於可以了
這裏是寫掃描線代碼需要注意的地方:
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就夠了