zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Redis(八)理解内存
    Redis(七)Redis的噩梦:阻塞
    Redis(六)复制
    Redis(五)持久化
    笔试面试经典问题
    两个栈实现一个队列
    单链表相关操作
    我的笔记本
    10进制正整数转4位定长的36进制字符串
    微软2016校园招聘在线笔试之Magic Box
  • 原文地址:https://www.cnblogs.com/lawyer/p/6776972.html
Copyright © 2011-2022 走看看