• [HDU 6759]Leading Robots


    Description

    题库链接

    给出 (n) 个二次函数 (f_i(t)=frac{1}{2}a_it^2+p_i)。问函数 (g(t)=maxlimits_{1leq ileq n}{f_i(t)},tin[0,+infty)) 是由几个函数组成的。若 (t_0) 时刻同时有多个 (f) 为最大值,那么 (g) 函数上 (t=t_0) 不能被考虑。多测,测试组数 (t)

    (1leq nleq 50000,1leq tleq 50)

    Solution

    我的做法有点复杂。

    首先可以确定,当 (a) 相等时,只需要保留最大的 (p) 所对应的二次函数即可。因此可以保证下述讨论中 (a),均不相同。将处理后的函数按 (a) 从小到大排序。

    对于第 (i) 个函数,若它能在某个时刻最大,那么 [egin{aligned}forall j eq i,exists t_0,&frac{1}{2}a_it_0^2+p_i>frac{1}{2}a_jt_0^2+p_j\Rightarrow&frac{1}{2}t_0^2(a_i-a_j)>p_j-p_i\Rightarrow&left{egin{aligned}frac{1}{2}t_0^2>frac{p_j-p_i}{a_i-a_j},&i>j\frac{1}{2}t_0^2<frac{p_j-p_i}{a_i-a_j},&i<jend{aligned} ight.end{aligned}]

    (m_1=maxlimits_{1leq j< i}left{frac{p_j-p_i}{a_i-a_j} ight})(m_2=minlimits_{i< jleq n}left{frac{p_j-p_i}{a_i-a_j} ight}),也就是说,如果第 (i) 个函数满足 (m_2>0land m_2>m_1)。那么第 (i) 个函数就会在某个时刻有最大值。是可以被统计入答案中的。(注意判断相同的函数以及在 (t=0) 处最大的这两种情况)

    那么现在只需要求出 (m_1,m_2) 这一问题就可解了。现在考虑求出所有 (i)(m_1)

    要求 (maxlimits_{1leq j< i}left{frac{p_j-p_i}{a_i-a_j} ight}),也就是求 (-minlimits_{1leq j< i}left{frac{p_i-p_j}{a_i-a_j} ight})。也就是考虑如何求 (i) 以前所有点 ((a_j, p_j)) 与点 ((a_i, p_i)) 连线的斜率最小值。显然当这一点与 (1sim i-1) 组成的点集上凸包相切的时候会有答案。因此开一个单调队列维护上凸包,查询时二分凸包即可。

    (m_2) 用相似的过程倒着来一遍。

    复杂度 (O(tcdot nlog n))

    Code

    #include <bits/stdc++.h>
    #define pii pair<long long, long long>
    #define fr first
    #define sc second
    #define a(i) (b[i].fr)
    #define p(i) (b[i].sc)
    using namespace std;
    const int N = 50000+5;
    
    int t, n, tot, kp[N], vis[N];
    pii a[N], b[N];
    int q[N], top, ANS;
    
    int main() {
        scanf("%d", &t);
        while (t--) {
            scanf("%d", &n); tot = 0;
            for (int i = 1; i <= n; i++)
                scanf("%lld%lld", &a[i].sc, &a[i].fr);
            sort(a+1, a+n+1); a[n+1].fr = -1;
            for (int i = 1; i <= n; i++) 
                if (a[i].fr != a[i+1].fr) {
                    if (a[i].fr != a[i-1].fr || a[i].sc != a[i-1].sc) {
                        b[++tot] = a[i], vis[tot] = 1;
                        
                    }
                    else if (a[i].fr == a[i-1].fr && a[i].sc == a[i-1].sc) b[++tot] = a[i], vis[tot] = 0;
                }
            n = tot; b[0].fr = b[1].fr-1, b[0].sc = -2147483647;
            top = 0;
            for (int i = 1; i <= n; i++) {
                int l = 1, r = top, ans = 0, m, j, k;
                while (l <= r) {
                    m = (l+r)>>1, j = q[m], k = q[m-1];
                    if (1ll*(p(i)-p(j))*(a(j)-a(k)) < 1ll*(p(j)-p(k))*(a(i)-a(j))) ans = m, l = m+1;
                    else r = m-1;
                }
                kp[i] = q[ans];
                while (top && 1ll*(p(i)-p(q[top]))*(a(q[top])-a(q[top-1])) >= 1ll*(p(q[top])-p(q[top-1]))*(a(i)-a(q[top]))) --top;
                q[++top] = i;
            }
            if (n) ANS = vis[n];
            else ANS = 0;
            b[0].fr = 1ll+b[n].fr;
            q[top = 1] = n;
            for (int i = n-1; i >= 1; i--) {
                int l = 1, r = top, ans = top, m, j, k;
                while (l <= r) {
                    m = (l+r)>>1, j = q[m], k = q[m-1];
                    if (1ll*(p(i)-p(j))*(a(j)-a(k)) > 1ll*(p(j)-p(k))*(a(i)-a(j))) ans = m, l = m+1;
                    else r = m-1;
                }
                int x = kp[i], y = q[ans];
                if (p(i) > p(y) && 1ll*(p(i)-p(x))*(a(y)-a(i)) > 1ll*(p(i)-p(y))*(a(x)-a(i))) ANS += vis[i];
                while (top && 1ll*(p(i)-p(q[top]))*(a(q[top])-a(q[top-1])) <= 1ll*(p(q[top])-p(q[top-1]))*(a(i)-a(q[top]))) --top;
                q[++top] = i;
            }
            printf("%d
    ", ANS);
        }
        return 0;
    }
  • 相关阅读:
    修复火狐主页被篡改成hao123的办法
    VMware中装Win2012并配置Hyper-v
    Linux下随机密码生成器
    GNS3 桥接虚拟网卡 telnet 实验
    冰点文库下载器停止工作解决办法
    《循序渐进》之简单的DHCP实验
    windows脚本配置ip地址
    phpmyadmin使用中碰到的一些问题
    phpmyadmin导入导出大数据文件的办法
    phpmyadmin的安装和使用
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/13455687.html
Copyright © 2020-2023  润新知