半平面交.....

    · 博主受虐中...

    · Delayyy君 · 真 · 神犇

    · 代码仍然不堪入目



    曾经写过一次半平面交...

    因为完全没搞懂就稀里糊涂过了...

    今早考试整个人就被虐成了渣...


    推荐:

    1、http://wenku.baidu.com/view/e59decfefab069dc502201f2.html

    (太懒了完全没认真找)


   话说御酱的作业系列还是一如既往的带感...

   回正题...

   其实个人认为[1]很详细了...

   无非就是维护一个双端队列什么的...

   不过通常来说,思想容易...代码却总是萎成渣一样...

   以下代码...  (原题 HNOI2012 射箭)

   半平面用两点式向量存的,向量左边为半平面. (果然还是两点式容易理解... )

   

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define db double
using namespace std;

int tail, head, ap, v[200010], q[200010];
int x, y, z, n;
struct point { db x, y; } ser[200010];
struct plane { int r, t;  point a, b; }  p[200010];
db cx(point a, point b, point c)  {  return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);  }
point cp(plane a, plane b)
{
  db sep = cx(a.a, b.a, b.b);
  sep = sep / (sep - cx(a.b, b.a, b.b));
  return (point)  { a.a.x + (a.b.x - a.a.x) * sep, a.a.y + (a.b.y - a.a.y) * sep };
}
void setPlane(int tp, int x, int y, int t)
{
  p[tp].r = x;
  p[tp].t = t;
  p[tp].a = (point)  { 0, x ? (db) y / x : y};
  p[tp].b = (point)  { 1, p[tp].a.y - x};
  if (tp > n)  swap(p[tp].a, p[tp].b);
}
bool check(int max_t)
{
  int max_n = 2 * n + 1;
  ap = 0;
  for (int i = 0; i <= max_n; ++i)
	if (p[i].t <= max_t)
	  v[++ap] = i;

  tail = (head = 1) - 1;
  for (int i = 1; i <= ap; ++i)  {
	int lap = v[i];
	while (head < tail  &&  cx(p[lap].a, p[lap].b, ser[tail]) < 0)  tail--;
	while (head < tail  &&  cx(p[lap].a, p[lap].b, ser[head + 1]) < 0)  head++;
	q[++tail] = lap;
	if (tail != head)
	  ser[tail] = cp(p[q[tail - 1]], p[q[tail]]);
  }
  
  while (head < tail - 1  &&  cx(p[q[tail]].a, p[q[tail]].b, ser[head + 1]) < 0)  head++;
  while (head < tail - 1  &&  cx(p[q[head]].a, p[q[head]].b, ser[tail]) < 0)  tail--;
  return tail - head >= 2;
}
bool cmp(const plane &a, const plane &b)  {  return a.r > b.r  ||  (a.r == b.r  &&  a.a.y > b.a.y); }
bool cmP(const plane &a, const plane &b)  {  return a.r > b.r  ||  (a.r == b.r  &&  a.a.y < b.a.y); }
int main()
{
  freopen("archery.in", "r", stdin);
  freopen("archery.out", "w", stdout);

  scanf("%d", &n);
  for (int i = 1; i <= n; ++i)  {
    scanf("%d %d %d", &x, &y, &z);
	setPlane(i, x, y, i);
	setPlane(i + n, x, z, i);
  }

  setPlane(0, 0, 0, 0);
  setPlane(2 * n + 1, 0, (int) 1e9, 0);
  sort(p, p + n + 1, cmp);
  sort(p + n + 1, p + 2 * n + 2, cmP);

  int l = 1, r = n, j, ans;
  for (; j = (l + r) >> 1, l <= r; )
	if (check(j))  ans = j, l = j + 1;
	else  r = j - 1;

  printf("%d", ans);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值