思路:
建议先做
HDU 1542 | Atlantis |
是一样的题,不妨先A了 1542再来搞这题。
改变的只是求矩阵的交, 那么我们只是要考虑如何能找到一个区域可以被重复的覆盖即可。
只要找到cover标记,如果是>1的 则表示这个线左侧有至少两条,那么必定是交区域
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<cmath>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=2005;
int n;
double y[maxn];
struct linec // 存储线段信息;
{
double x; // 该线段所在的位置;
double y_up,y_down; // 竖向线段的上下端点;
int flag;
}line[maxn];
struct node
{
double left,right;
double x; // 记录上一个横坐标位置,用于求面积;
int cover; // 记录覆盖的线段数;即同一方向的线段数;
bool flag; // 叶子节点
}tree[maxn*4];
bool cmp(linec a,linec b)
{
return a.x<b.x;
}
void build(int i,int left,int right)
{
tree[i].left=y[left];
tree[i].right=y[right];
tree[i].x=-1;
tree[i].flag=false;
tree[i].cover=0;
if(left+1==right)
{
tree[i].flag=true;
return ;
}
int mid=(left+right)>>1;
build(i<<1,left,mid);
build(i<<1|1,mid,right);
}
double insert_query(int i,double x,double left,double right,int flag)
{
if(left>=tree[i].right||right<=tree[i].left)
return 0;
if(tree[i].flag)
{
if(tree[i].cover>1)
{
double pre=tree[i].x;
double ans=(x-pre)*(tree[i].right-tree[i].left);
tree[i].x=x;
tree[i].cover+=flag;
return ans;
}
else
{
tree[i].x=x;
tree[i].cover+=flag;
return 0;
}
}
double ans1=insert_query(i<<1,x,left,right,flag);
double ans2=insert_query(i<<1|1,x,left,right,flag);
return ans1+ans2;
}
int main()
{
int t;
scanf("%d",&t);
int Case=0;
double x1,x2,y1,y2;
while(t--)
{
scanf("%d",&n);
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
y[++cnt]=y1;
line[cnt].x=x1;
line[cnt].y_down=y1;
line[cnt].y_up=y2;
line[cnt].flag=1; // 表示左边线段;
y[++cnt]=y2;
line[cnt].x=x2;
line[cnt].y_down=y1;
line[cnt].y_up=y2;
line[cnt].flag=-1; // 表示右边线段;
}
sort(y+1,y+cnt+1); // 将所有高度由小到大排序,将区间建树表示;
sort(line+1,line+cnt+1,cmp); // 排序,返回坐标x靠左的点;
build(1,1,cnt);
double area=0;
for(int i=1;i<=cnt;i++)
{
area+=insert_query(1,line[i].x,line[i].y_down,line[i].y_up,line[i].flag);
}
printf("%.2lf\n",area);
}
return 0;
}
/*
3
10 10 20 20
10 10 20 20
10 10 20 20
*/