POJ-2318

挺简单的一道题,我看到n和m都是5000觉得暴力应该是没有问题的,然后就写了个m*n的遍历,T到毫无朋友。。。
后来感觉应该用二分,不过总觉得这道题的二分应该很诡异,自己的姿势不好可能会写崩,再加上看见discuss里面一群人说暴力可过,就无耻的信了。。。
然后就改呗=_=比如说把函数都加inline啊,形参都加const (ElemType)&啊,循环里加个break啊,去掉几个特判啊。。。。。。
然而这并没有用(desu)
所以说最后死心塌地的写二分,居然不用debug一遍就过了!
最后PS:给c++跪了,以下代码交C++CE。。。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
#include <iostream>
#include <algorithm>
using namespace std;
const double eps = 1e-9;
struct P
{
    double x, y;
    P() {}
    P(double x, double y) : x(x), y(y) {}
    double add(double a, double b)
    {
        if(abs(a + b) < eps * (abs(a) + abs(b))) return 0;
        else return a + b;
    }
    P operator + (const P &q)
    {
        return P(add(x, q.x), add(y, q.y));
    }
    P operator - (const P &q)
    {
        return P(add(x, -q.x), add(y, -q.y));
    }
    P operator * (const double &b)
    {
        return P(x * b, y * b);
    }
    bool operator == (const P &q)
    {
        return x == q.x && y == q.y;
    }
    double det(const P &q)
    {
        return x * q.y - y * q.x;
    }
    double dot(const P &q)
    {
        return x * q.x + y * q.y;
    }
};
int part[5117];
double part_up[5117], part_down[5117], x1, x2, y1, y2;
P toys[5117];
int n, m;

inline void init()
{
    memset(part, 0, sizeof(part));
return ;
}

inline bool on_bound(P p, const P &up1, const P &down2)
{
    if(p.x == up1.x)
    {
        part[0] += 1;
        return true;
    }
    if(p.x == down2.x)
    {
        part[n] += 1;
        return true;
    }
    return false;
}

inline bool on_part(P p, int pos)
{
    P up1(0, y1), up2(0, y1), down1(0, y2), down2(0, y2);
    if(pos == 0)
    {
        up1.x = x1, up2.x = part_up[pos], down1.x = x1, down2.x = part_down[pos];
    }
    else
    {
        up1.x = part_up[pos - 1], up2.x = part_up[pos], down1.x = part_down[pos - 1], down2.x = part_down[pos];
    }
    if((down1 - up1).det(p - up1) * (up2 - down2).det(p - down2) > 0)
    {
        return true;
    }
return false;
}

void bin_search(int l, int r, P p)
{
    while(l <= r)
    {
        int mid = (l + r) / 2;
        if((p - P(part_down[mid], y2)).det(P(part_up[mid], y1) - P(part_down[mid], y2)) > 0)
        {
            if(!on_part(p, mid + 1)) l = mid + 1;
            else
            {
                part[mid + 1] += 1;
                return ;
            }
        }
        else if((p - P(part_down[mid], y2)).det(P(part_up[mid], y1) - P(part_down[mid], y2)) < 0)
        {
            if(!on_part(p, mid)) r = mid - 1;
            else
            {
                part[mid] += 1;
                return ;
            }
        }
    }
return ;
}

int main()
{
    int i, j, k, cse = 1;
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;
        scanf("%d %lf %lf %lf %lf", &m, &x1, &y1, &x2, &y2);
        init();
        for(i = 0; i < n; ++i)
        {
            scanf("%lf %lf", &part_up[i], &part_down[i]);
        }
        part_up[n] = part_down[n] = x2;
        P now;
        i = 0;
        P up1(x1, y1), down2(x2, y2);
        while(i < m)
        {
            scanf("%lf %lf", &now.x, &now.y);
            if(on_bound(now, up1, down2))
            {
                ++i;
                continue;
            }
            bin_search(0, n, now);
            ++i;
        }
        if(cse != 1) printf("\n");
        ++cse;
        for(i = 0; i <= n; ++i)
        {
            printf("%d: %d\n", i, part[i]);
        }
    }
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值