• Mike and distribution


    题意:

    给定 $n$ 个物品,每个物品有两个属性$a_i$, $b_i$,求一个长度为$[frac{n}{2}]+1$的子序列 $p$ 使得

    $2 * sum_{i = 1}^{|p|}{a_{p_i}} > sum_{i=1}^n {a_i}$

    $2 * sum_{i = 1}^{|p|}{b_{p_i}} > sum_{i=1}^n {b_i}$

    解法:

    非常巧妙的构造方法。

    注意到题目的要求可以转化为非 $p_i$ 的集合的元素之和小于 $p_i$内元素之和。

    考虑一种构造方法:

      首先按照$a_i$大小将物品从大到小进行排序。

      首先选上第一个物品,接下来对于后面的物品分成 $[frac{n-1}{2}]$ 个两对物品来看,

        对于每一对物品选取$b_i$较大的物品加入$p$集合。

      如果余下了一个物品,则加入$p$集合。

    正确性:

      首先对于$b$,显然有原题要求条件成立。

      对于$a$,可以发现 $a_1$ 大于后面所有 $a_{i+1} - a_i$ 的和,这样,也成立。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    #define N 100010
    
    using namespace std;
    
    int n;
    int a[N], p[N], b[N], c[N];
    
    bool cmp(int x, int y)
    {
        return a[x] > a[y];
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1;i <= n;i++) scanf("%d", &a[i]);
        for(int i = 1;i <= n;i++) scanf("%d", &b[i]);
        for(int i = 1;i <= n;i++) c[i] = i;
        sort(c + 1, c + n + 1, cmp);
        int tot = 0;
        p[tot = 1] = c[1];
        for(int i = 2;i <= n;i += 2)
        {
            if(i<n && b[ c[i] ] < b[ c[i+1] ]) p[++tot] = c[i+1];
            else p[++tot] = c[i];
        }
        sort(p + 1, p + tot + 1);
        cout << tot << endl;
        for(int i = 1;i <= tot;i++) cout << p[i] << ' ';
        cout << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    在 SVG 中添加交互性
    大型Web2.0站点构建技术初探 (转)
    鼠标右键右键菜单
    用SVG技术实现动态图形输出的嵌入式Web服务
    使用脚本动态操作 SVG 文档
    GDI+技术的坐标解决方案
    一个项目的粗略流程
    xml矢量图:svg的viewBox和vml的coordsize决定的虚坐标系简说
    用VML画图(一些基本的矢量图)
    列出本地可用字体
  • 原文地址:https://www.cnblogs.com/lawyer/p/6776972.html
Copyright © 2020-2023  润新知