zoukankan      html  css  js  c++  java
  • BZOJ2732[HNOI2012]射箭

    题目大意

    给出N条垂直于x轴的线段,求最大的K,使得存在一条经过原点,开口向下的抛物线穿过前K条线段(经过端点也算穿过),保证N条线段不重叠,且都在第一象限。

    输入输出

    第一行为一个整数N;

    接下来N行每行3个整数x,y1,y2,描述一条线段。

    数据范围

    N≤100000,0<x≤1e9,0<y1<y2≤1e9。

    解析

    设抛物线方程为ax2+bx,则y1≤ax2+bx≤y2;

    可以把每条线段看成两个关于a,b的不等式,由于是一次的,可以用半平面交验证答案。于是二分K,验证是否可行。

    几个细节:

    1)半平面在向量哪边要想清楚;

    2)由于经过端点也算穿过,所以半平面交的边上也是可行的,极端情况所有直线交于一点,不知道有没有这种数据;

    3)抛物线开口向下,对称轴在第一象限,增加2个向量限制a<0,b>0;

    4)为了方便判断半平面交是否为空,可以增加2个“边框”向量,但是这两个向量的起止点坐标要足够大(反正我开1e12WA了);

    5)开long double;

    6)全部排序后根据id加入半平面交O(nlogn)比每次二分都排一次序O(nlog2n)优秀(废话)。

    代码

            一直T竟然是因为求交点的方法不够优秀,代码过于丑陋必须加读入优化才能过qwq。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <iomanip>
      5 #include <cmath>
      6 #include <algorithm>
      7 
      8 typedef long long LL;
      9 typedef long double LD;
     10 const LD INF = 1e15;
     11 struct Point {
     12 	LD x, y;
     13 	Point(LD _x = 0, LD _y = 0):x(_x), y(_y) {};
     14 };
     15 struct Vector {
     16 	Point st, ed;
     17 	int id;
     18 	LD arg;
     19 	Vector() { memset(this, 0, sizeof(Vector)); }
     20 	Vector(Point _st, Point _ed):st(_st), ed(_ed), id(0) {};
     21 	bool operator <(const Vector &) const;
     22 	friend LD cross(const Vector &, const Vector &);
     23 	friend Point intersection(const Vector &, const Vector&);
     24 } line[200010];
     25 int N;
     26 
     27 bool judge(int);
     28 bool check(const Vector &, const Vector &, const Vector &);
     29 inline char gc();
     30 inline int read();
     31 
     32 int main() {
     33 #ifndef ONLINE_JUDGE
     34 	freopen("2732.in", "r", stdin);
     35 	freopen("2732.out", "w", stdout);
     36 #endif
     37 	N = read();
     38 	line[0] = Vector(Point(0, -INF), Point(0, INF));
     39 	line[1] = Vector(Point(-INF, 0), Point(INF, 0));
     40 	for (int i = 1; i <= N; i++) {
     41 		LD x = read(), y1 = read(), y2 = read();
     42 		line[i << 1] = Vector(Point(-1, y1 / x + x), Point(1, y1 / x - x));
     43 		line[i << 1 | 1] = Vector(Point(1, y2 / x - x), Point(-1, y2 / x + x));
     44 		line[i << 1].id = line[i << 1 | 1].id = i;
     45 	}
     46 	int l = 1, r = N;
     47 	N = (N << 1 | 1);
     48 	line[++N] = Vector(Point(-INF, INF), Point(-INF, -INF));
     49 	line[++N] = Vector(Point(INF, INF), Point(-INF, INF));
     50 	for (int i = 0; i <= N; i++)
     51 		line[i].arg = atan2(line[i].ed.y - line[i].st.y, line[i].ed.x - line[i].st.x);
     52 	std::sort(line, line + N + 1);
     53 	while (l < r) {
     54 		int mid = (l + r + 1) >> 1;
     55 		if (judge(mid)) l = mid;
     56 		else r = mid - 1;
     57 	}
     58 	printf("%d
    ", l);
     59 
     60 	return 0;
     61 }
     62 bool Vector::operator <(const Vector &v) const {
     63 	if (arg != v.arg) return arg < v.arg;
     64 	else return cross(*this, Vector(st, v.st)) <= 0;
     65 }
     66 LD cross(const Vector &a, const Vector &b) {
     67 	return (a.ed.x - a.st.x) * (b.ed.y - b.st.y) - (a.ed.y - a.st.y) * (b.ed.x - b.st.x);
     68 }
     69 Point intersection(const Vector &a, const Vector &b) {
     70 	LD s1 = cross(Vector(a.st, b.ed), a);
     71 	LD s2 = cross(a, Vector(a.st, b.st));
     72 	LD t = s2 / (s1 + s2);
     73 	return Point(b.st.x + t * (b.ed.x - b.st.x), b.st.y + t * (b.ed.y - b.st.y));
     74 }
     75 bool check(const Vector &a, const Vector &b, const Vector &c) {
     76 	Point p = intersection(a, b);
     77 	return cross(Vector(c.st, p), c) > 0;
     78 }
     79 bool judge(int lim) {
     80 	static Vector ls[200010], res[200010];
     81 	int tot = 0, head = 0, tail = 0;
     82 	for (int i = 0; i <= N; i++)
     83 		if (line[i].id <= lim) ls[tot++] = line[i];
     84 	for (int i = 0; i < tot; i++) {
     85 		if (i && ls[i].arg == ls[i - 1].arg) continue;
     86 		while (tail - head > 1 && check(res[tail - 2], res[tail - 1], ls[i])) tail--;
     87 		while (tail - head > 1 && check(res[head], res[head + 1], ls[i])) head++;
     88 		res[tail++] = ls[i];
     89 	}
     90 	while (tail - head > 2 && check(res[tail - 2], res[tail - 1], res[head])) tail--;
     91 	while (tail - head > 2 && check(res[head], res[head + 1], res[tail - 1])) head++;
     92 	return tail - head > 2;
     93 }
     94 inline char gc() {
     95 	static char buf[1000000], *p1, *p2;
     96 	if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin);
     97 	return p1 == p2 ? EOF : *p2++;
     98 }
     99 inline int read() {
    100 	int res = 0, op = 1;
    101 	char ch = gc();
    102 	while (ch != '-' && (ch < '0' || ch > '9')) ch = gc();
    103 	if (ch == '-') op = 1, ch = gc();
    104 	while (ch >= '0' && ch <= '9')
    105 		res = (res << 1) + (res << 3) + ch - '0', ch = gc();
    106 	return res * op;
    107 }
  • 相关阅读:
    vue-cli快速搭建
    js严格模式下判断数据类型
    js实现本地的图片压缩上传预览
    web端实现图片放大切换显示预览
    swiper.js在隐藏/显示切换时,轮播出现bug的解决办法
    Zepto.js实现fadeIn,fadeOut功能
    ms
    redis 解决秒杀
    单下滑线 事务 锁
    极验
  • 原文地址:https://www.cnblogs.com/Rhein-E/p/10268390.html
Copyright © 2011-2022 走看看