BUREK
贝克金宝有N个三角形。他的儿子乔伊有一个很大的刀,准备切割这些三角形。每一次切割,乔伊能够用与x轴平行的直线(y=c)或与y轴平行的直线(x=c)对这些三角形进行切割。
你的任务是计算每一次切割,有多少个三角形会被切割。
注意:
被切割过的三角形仍看作一个三角形;
三角形被切割当且仅当三角形在直线以左的部分的面积和在直线以右的部分的面积,都应大于0。
输入 第一行是一个正整数N(2<=N<=100000),三角形的个数。
第2到N+1行每行包含6个整数x1,y1,x2,y2,x3,y3表示三角形的三个顶点(x1,y1),(x2,y2),(x3,y3)(保证这三个点不共线)0<=x1,y1,x2,y2,x3,y3<=1000000
第N+2行是一个正整数M(2<=M<=100000),切割的次数。
第N+3到N+M+2行包含一个直线方程“x=c”或“y=c”(注意等号两旁的空格)0<=c<=1000000。
输出
每一次切割,输出一行包含切割的三角形数量。
至少40%的数据M<=300
另外40%的数据三角形顶点的坐标小于1000
给个100%不行吗,wa了10遍,全在数据范围上
因为每一次都是对一条平行于X轴或者Y轴的直线进行切割,如果这条线穿过了该三角形的其中一条边(不考虑顶点,因为两部分面积均要大于)就可以讲该三角形切割成两部分。
1 当沿着平行于Y轴的直线进行切割时(x==k)时如果可以切开这个三角形,就说明(min(三角形的x坐标)<k<max(三角形的x坐标))所以可以对三角形的X坐标进行差分,然后求前缀和,求出每一个x=k被切割时,经过这个线的三角形的个数,然后直接O(1)查询即可
2当沿着平行于X轴的直线进行切割时同理,处理Y坐标。
#include<bits/stdc++.h>
using namespace ;
const ll maxn=1e6+7;
const ll inf = 0x3f3f3f3f;
inline ll read()
{
ll x=0;bool f=0;char ch=getchar();
while (ch<'0'||'9'<ch)
f|=ch=='-', ch=getchar();
while ('0'<=ch && ch<='9')
x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
ll a[maxn],b[maxn];//x.y;
ll sumx[maxn],sumy[maxn];
char s[1000000];
int main()
{
ll n;
cin>>n;
ll cnt1,cnt2;
ll x1,y1,x2,y2,x3,y3;
ll maxsx=-inf,maxsy=-inf;
for(ll i=1;i<=n;i++)
{
x1=read(),y1=read();
x2=read(),y2=read();
x3=read(),y3=read();
cnt1=max(x1,max(x2,x3));
cnt2=min(x1,min(x2,x3));
maxsx=max(maxsx,cnt1);
a[cnt1]--; a[cnt2+1]++;
cnt1=max(y1,max(y2,y3));
cnt2=min(y1,min(y2,y3));
b[cnt1]--; b[cnt2+1]++;
maxsy=max(maxsy,cnt1);
}
sumx[0]=a[0];
sumy[0]=b[0];
for(ll i=1;i<=max(maxsx,maxsy);i++)//求出来最大的x,y在进行求前缀和
{
sumx[i]=sumx[i-1]+a[i];
sumy[i]=sumy[i-1]+b[i];
}
ll t;
cin>>t;
char ttt;
//getchar();
while(ttt!='\n')
ttt=getchar();
while(t--)
{
gets(s);
ll len=strlen(s);
int sum=0;
for(ll i=4;s[i]>='0'&&s[i]<='9'&&i<len;i++)
{
sum=sum*10+(s[i]-'0');
}
if(s[0]=='x')
{
printf("%lld\n",sumx[sum]);
}
else printf("%lld\n",sumy[sum]);
}
}