完全相同与poj 1511,可以直接离散化来做,也可以”离散化+线段树+扫描线“搞定,方正方法不止一种;
离散化的程序:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define N 1002
int t;
int serch(int *arr,int key)
{
int low,high,mid;
low=0,high=2*t-1;
while(low<=high)
{
mid=(low+high)/2;
if(key==arr[mid])return mid;
if(key>arr[mid])low=mid+1;
else high=mid-1;
}
return 0;
}
int main()
{
int x[2*N],y[2*N],s[N][4];
bool xy[2*N][2*N];
while(1)
{
t=0;
while(scanf("%d%d%d%d",&s[t][0],&s[t][1],&s[t][2],&s[t][3])!=EOF)
{
if(s[t][0]==-1&&s[t][1]==-1&&s[t][2]==-1&&s[t][3]==-1)break;
else t++;
}
if(t)
{
int k=0;
for(int i=0;i<t;i++)
{
x[k]=s[i][0];
y[k]=s[i][1];
k++;
x[k]=s[i][2];
y[k]=s[i][3];
k++;
}
sort(x,x+k);
sort(y,y+k);
memset(xy,false,sizeof(xy));
for(int i=0;i<t;i++)
{
int f1=serch(x,s[i][0]);
int f2=serch(x,s[i][2]);
int f3=serch(y,s[i][1]);
int f4=serch(y,s[i][3]);
for(int j=f1;j<f2;j++)
{
for(int k=f3;k<f4;k++)
{
xy[j][k]=true;
}
}
}
int area=0;
for(int i=0;i<2*t;i++)
{
for(int j=0;j<2*t;j++)
{
area+=(x[i+1]-x[i])*(y[j+1]-y[j])*xy[i][j];
}
}
printf("%d\n",area);
continue;
}
else return 0;
}
return 0;
}
离散化+线段树+扫描线的程序:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define N 1002
struct SegTree
{
int l,r,mid;
int c,m;
}tree[N*3];
struct Line
{
bool flag;
int y1,y2,x;
}line[2*N];
int t;
int y[2*N];
bool cmp(Line a,Line b)
{
return a.x<b.x;
}
void BulidTree(int root,int l,int r) //建立线段树
{
tree[root].l=l;
tree[root].r=r;
tree[root].c=0;
tree[root].m=0;
tree[root].mid=(l+r)/2;
if(l+1==r)return;
BulidTree(2*root,l,tree[root].mid);
BulidTree(2*root+1,tree[root].mid,r);
}
int serch(int *arr,int num,int key)
{
int low,high,mid;
low=0,high=num-1;
while(low<=high)
{
mid=(low+high)/2;
if(arr[mid]==key)return mid;
if(key>arr[mid])low=mid+1;
else high=mid-1;
}
return 0;
}
void Updata(int root)
{
if(tree[root].c>0)tree[root].m=y[tree[root].r]-y[tree[root].l];
else if(tree[root].r-tree[root].l==1)tree[root].m=0;
else tree[root].m=tree[2*root].m+tree[2*root+1].m;
}
void insert(int root,int l,int r)
{
if(l<=tree[root].l&&tree[root].r<=r)
{
tree[root].c++;
Updata(root);
return;
}
if(tree[root].r-tree[root].l==1)return;
if(l<tree[root].mid)insert(2*root,l,r);
if(r>tree[root].mid)insert(2*root+1,l,r);
Updata(root);
}
void Delet(int root,int l,int r)
{
if(l<=tree[root].l&&tree[root].r<=r)
{
tree[root].c--;
Updata(root);
return;
}
if(tree[root].r-tree[root].l==1)return;
if(l<tree[root].mid)Delet(2*root,l,r);
if(r>tree[root].mid)Delet(2*root+1,l,r);
Updata(root);
}
int main()
{
while(1)
{
int x1,y1,x2,y2;
int ty[2*N];
t=0;
while(scanf("%d%d%d%d",&x1,&y1,&x2,&y2)!=EOF)
{
if(x1==-1&&y1==-1&&x2==-1&&y2==-1)break;
else
{
line[2*t].flag=true;
line[2*t].x=x1;
line[2*t].y1=y1;
line[2*t].y2=y2;
line[2*t+1].flag=false;
line[2*t+1].x=x2;
line[2*t+1].y1=y1;
line[2*t+1].y2=y2;
ty[2*t]=y1;
ty[2*t+1]=y2;
t++;
}
}
if(t)
{
t<<=1;
sort(line,line+t,cmp);
sort(ty,ty+t);
y[0]=ty[0];
int num;
for(int i=num=1;i<t;i++)
{
if(ty[i]!=ty[i-1])
{
y[num++]=ty[i]; //将纵坐标去重成功
}
}
BulidTree(1,0,num-1); //建立线段树
int area=0;
for(int i=0;i<t;i++)
{
int l=serch(y,num,line[i].y1);
int r=serch(y,num,line[i].y2);
if(line[i].flag)insert(1,l,r);
else Delet(1,l,r);
area+=tree[1].m*(line[i+1].x-line[i].x);
}
printf("%d\n",area);
continue;
}
else return 0;
}
return 0;
}
其实,感觉都是模式化的。只要多写多练多体会,这些还是能够很好的掌握的!