牛客练习赛36 F-Rabbit的蛋糕 (叉积求面积, 记录前缀)

题目链接

题目描述

Rabbit和xxx获得了一个很大的蛋糕,这个蛋糕实际上是由N个点组成的凸多边形(点从1到N编号,保证没有三点共线)。
接着两个人开始分蛋糕,他们准备沿着蛋糕上两点连成的直线把蛋糕切成两份,由于Rabbit是女生,xxx总会把大的那一份分给Rabbit。现在有Q种切的方案,xxx可以选择任意一种,问xxx最多能分得多少蛋糕?

输入描述:

第一行两个整数N,Q。
接下来N行,每行两个数xi,yi表示第i个点的坐标(点按逆时针顺序给出)。
接下来Q行,每行两个整数S,T表示切的两个点。

输出描述:

输出xxx最多能分得多少面积的蛋糕。

输入

4 2
0.5 0.5
10.5 0.5
10.5 10.5
0.5 10.5
1 3
4 2

输出

50.00

思路
  • 暴力枚举TLE

  • 记录从起点到每个点的面积,这样任意平分的面积就可以表示:
    在这里插入图片描述
    S3 = S - S1 - S2

  • 叉积求面积:
    在这里插入图片描述

#include <bits/stdc++.h>
#define LL  long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define maxn 100005
using namespace std;
struct ac{
    double x, y;
    friend double operator * (const ac t1, const ac t2) {
        double sum = t1.x * t2.y - t1.y * t2.x;
        return abs(sum);
    }
    friend ac operator - (const ac t1, const ac t2) {
        return {t1.x - t2.x, t1.y - t2.y};
    }
}a[maxn];
int N, Q;
double pre[maxn];


int main() {
#ifndef ONLINE_JUDGE
   freopen("in.txt", "r", stdin);
   // freopen("out.txt", "w", stdout);
#endif
    scanf("%d %d", &N, &Q);
    pre[1] = pre[2] = 0;
    REP (i, N) {
        scanf("%lf %lf", &a[i].x, &a[i].y);
        if (i >= 3) {
            pre[i] = pre[i-1] + (a[1] - a[i-1]) * (a[1] - a[i]);
        }
    }
    double ans = 0.0;
    rep (i, Q) {
        int S, T;
        scanf("%d %d", &S, &T);
        if (S > T)  swap(S, T);
        double sum = pre[T] - pre[S] - (a[1] - a[S]) * (a[1] - a[T]);
        sum = min(sum, pre[N] - sum);
        ans = max(sum, ans);
    }

    printf("%.10lf\n", ans / 2);

    return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值