洛谷4623 [COCI2012-2013#6] BUREK
阅读原文时间:2023年07月12日阅读:2

给定N个三角形,和M条直线,直线要么平行于X轴,要么平行于Y轴,问这M条直线 分别经过多少个三角形内部 (注意是内部即分开的两个多边形的面积均大于零)。

输入格式:

第一行一个正整数 N(2≤N≤100000)表示三角形的个数。 接下来N行,每行三个坐标(x1​,y1​), (x2​,y2​), (x3​,y3​) 表示三点,且这三点不共线。所有 坐标均为非负整数且小于106,三角形可以重叠。 接下来一个正整数M (2≤M≤100000)(,表示M个直线。 接下来M行,每行描述一条直线。"x =c"或"y= c" (注意等号两边的空格) c为非负整数,且小于10^

输出格式:

每一条直线输出一个整数,表示它穿过的三角形的个数。

输入样例#1:

3
1 0 0 2 2 2
1 3 3 5 4 0
5 4 4 5 4 4
4
x = 4
x = 1
y = 3
y = 1

输出样例#1:

0
1
1
2

输入样例#2:

4
2 7 6 0 0 5
7 1 7 10 11 11
5 10 2 9 6 8
1 9 10 10 4 1
4
y = 6
x = 2
x = 4
x = 9

输出样例#2:

3
2
3
2

  • 对于40%的数据M≤300
  • 另有40%的数据,所有三角形的坐标小于1000.

因为直线要么平行于X轴,要么平行于Y轴

所以我们把每个三角形 简化成 其X,Y方向上投影的两条线段,然后判断所求直线与这些线段的交点个数就好了

这个坐标都是整点,于是把每条线段覆盖的区间+1,这样的话 就能直接得到 所求点被多少条线段覆盖了

区间加可以直接通过差分实现

#include
#include
#include
#define MAXN 1000005
int N,M,p[MAXN],t[MAXN],P[MAXN],T[MAXN];
char c[];
using namespace std;
int main()
{
scanf("%d",&N);
for(int i=;i<=N;i++){ int xa,xb,xc,ya,yb,yc,u,d,l,r; scanf("%d%d%d%d%d%d",&xa,&ya,&xb,&yb,&xc,&yc); r=max(xa,xb),l=min(xa,xb),u=max(ya,yb),d=min(ya,yb); r=max(xc, r),l=min(xc, l),u=max(yc, u),d=min(yc, d); t[l+]++,t[r]--,p[d+]++,p[u]--;           //差分数组,区间(l,r) +1 } for(int i=;i<=;i++) T[i]=T[i-]+t[i],P[i]=P[i-]+p[i]; scanf("%d",&M); for(int i=;i<=M;i++) { int z;cin>>c[]>>c[]>>z;
if(c[]=='x')printf("%d\n",T[z]);
if(c[]=='y')printf("%d\n",P[z]);
}
// system("pause");
return ;
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器