sgu 277 动态凸包

做法和上一篇的那个题一样,每次删掉一个点把相应的面积加上即可,不过细节问题折腾了我一个下午,所幸AC了,不过代码已使我目不忍视了。

删点的时候需要考虑左右交界处要加上的是一个三角形还是两个三角形 ,各种细节改天附图说明,今天已经废了

贴上代码,有少量debug用的数据

/*

 0 0 -1 0 0 -1
 2
 0 -2
 1 0

 4

 1 0 0 3 3 2
 5
 1 2
 2 1
 3 0
 2 3
 0 1

 0 0 1 1 2 0
 4
 1 0
 0 2
 1 2
 2 2

 2
 4
 6
 8


 0 1 1 0 2 0
 3
 0 0
 3 0
 1 -1


 2
 3
 6


 0 0 1 1 2 0
 4
 1 -1
 -1 0
 1 2
 3 0

 4
 6
 9
 12



 */


#include <cstdio>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100010;
typedef pair<int, int> pii;
typedef long long lld;
#define two(i) (lld)1<<i;
#define MP make_pair
#define X first
#define Y second
map<int, int>::iterator it, p, q;
map<int, int> convex[2];
lld sum;
lld cross(pii a, pii b, pii c) {
  return (lld) (b.X - a.X) * (c.Y - a.Y) - (lld) (b.Y - a.Y) * (c.X - a.X);
}
bool judge(map<int, int> &st, int x, int y) {
  if (!st.size())
    return false;
  if (st.find(x) != st.end())
    return y >= st[x];
  if (x < st.begin()->X || (--st.end())->X < x)
    return false;
  it = st.lower_bound(x);
  p = q = it;
  p--;
  return cross(MP(x, y), *q, *p) <= 0;
}
void insert(map<int, int> &st, int x, int y) {
  if (judge(st, x, y))
    return;
  if (st.size() < 2) {  st[x] = y;  return;   }
  it = st.lower_bound(x);
  q = p = it;
  if (it != st.end()) {
    if (it == st.begin()) {
      q++;
      if (it->X == x)
        sum += cross(MP(x, y), *q, *it);
    } else {
      p--;
      q++;
      sum += (cross(MP(x, y), *it, *p));
      if (it->X == x && q != st.end())
        sum += cross(MP(x, y), *q, *it);
    }
  }
  st[x] = y;
  it = st.find(x);
  lld tmp;
  for (; it != st.begin();) {
    p = it;
    p--;
    if (p == st.begin())   break;
    q = p;
    q--;
    if ((tmp = cross(*it, *p, *q)) >= 0) {
      sum += tmp;
      st.erase(p);
    } else  break;
  }
  while (true) {
    p = it;
    p++;
    if (p == st.end())
      break;
    q = p;
    q++;
    if (q == st.end())  break;
    if ((tmp = cross(*it, *p, *q)) <= 0) {
      sum += -tmp;
      st.erase(p);
    } else   break;
  }
}
lld Abs(lld a) {
  if (a < 0)
    a = -a;
  return a;
}
void special(int x, int y) { // 上凸包与下凸包的交界处 , 如果是一条竖直的线,就需要特判了
  int ax = (--convex[0].end())->X;
  int bx = (--convex[1].end())->X;
  if (ax == bx && x > ax) {
    p = --convex[0].end();
    q = --convex[1].end();
    sum += Abs(cross(MP(x, y), *p, MP(q->X, -q->Y)));
  }
  ax = (convex[0].begin())->X;
  bx = convex[1].begin()->Y;
  if (ax == bx && x < ax) {
    p = convex[0].begin();
    q = convex[1].begin();
    sum += Abs(cross(MP(x, y), *p, MP(q->X, -q->Y)));
  }
}
int main() {
  int n, x, y;
  sum = 0;
  int xx[3], yy[3];
  for (int i = 0; i < 3; i++) {
    scanf("%d%d", &x, &y);
    xx[i] = x; yy[i] = y;
    insert(convex[0], x, y);
    insert(convex[1], x, -y);
  }
  sum = Abs(cross(MP(xx[0], yy[0]), MP(xx[1], yy[1]), MP(xx[2], yy[2])));
  scanf("%d", &n);
  while (n--) {
    scanf("%d%d", &x, &y);
    special(x, y);
    insert(convex[0], x, y);
    insert(convex[1], x, -y);
    printf("%lld\n", sum);
  }
  return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值