codeforce Gym 100685E Epic Fail of a Genie(MaximumProduction 贪心)

题意:给出一堆元素,求一个子集,使子集的乘积最大,如有多个,应该使子集元素个数尽量小。

题解:贪心,如果有大于1的正数,那么是一定要选的,注意负数也可能凑出大于1的正数,那么将绝对值大于1的负数两两配对,

如果还剩下一个绝对值大于1的负数,那么在判断一下,那个负数和比它大的最小负数的乘积是否大于1,如果是那么就选这两个。

把所有可能凑成大于1的数选完以后,剩下的数一定比1小,那么就不选。

如果无法凑出大于1的数,那么再分类讨论一下。

挺容易写错。。。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+6;

struct Num
{
    int a[maxn];
    int id[maxn];
    int r[maxn];
    int sz;
    Num(){sz = 0;}
    void push(double x,int i){
        a[sz] = x*100;
        r[sz] = sz;
        id[sz] = i;
        sz++;
    }

    int _upper_bound(int L,int R,int v)
    {
        while(L<R){
            int m = (L+R)>>1;
            if(a[r[m]]>v) R = m;
            else L = m+1;
        }
        return L;
    }

    int _lower_bound(int L,int R,int v)
    {
        while(L<R){
            int m = (L+R)>>1;
            if(a[r[m]]>=v) R = m;
            else L = m+1;
        }
        return L;
    }
   // int id(int x) { return r[x]; }

    int operator [](int x){
        return a[r[x]];
    }
}P,M;

int ans[maxn];

#define GetBound(l,r,v,which)\
l = which._lower_bound(0,which.sz,v);\
r = which._upper_bound(0,which.sz,v);

#define Add(which,x)\
ans[sz++] = which.id[which.r[x]];

bool cmp(int x,int y) { return P.a[x] < P.a[y]; }
bool cmp2(int x,int y) { return M.a[x] < M.a[y]; }



int main()
{
    //freopen("in.txt","r",stdin);
    int n; scanf("%d",&n);
    bool zero = false;
    int pzero;
    for(int i = 1; i <= n; i++){
        double t;
        scanf("%lf",&t);
        if(t>0){
            P.push(t,i);
        }else if(t<0){
            M.push(-t,i);
        }else if(!zero) {
            zero = true;
            pzero = i;
        }
    }
    sort(P.r,P.r+P.sz,cmp);
    sort(M.r,M.r+M.sz,cmp2);
    int m1l,m1r,p1l,p1r;
    GetBound(m1l,m1r,100,M)
    GetBound(p1l,p1r,100,P)

    int sz = 0;
    int t;
    for(t = p1r; t < P.sz; t++) Add(P,t)
    int odd = (M.sz - m1r)&1;
    for(t = m1r+odd; t < M.sz; t++) Add(M,t)
    if(odd){
        if(m1r>0 && M[m1r]/10000.*M[m1r-1] > 1 ) { Add(M,m1r) Add(M,m1r-1)  }
    }

    if(!sz){
        int psz = P.sz, msz = M.sz;
        if(psz){
            if(msz>=2 && M[msz-1]*M[msz-2] > P[psz-1]*100 ){
                Add(M,msz-1) Add(M,msz-2)
            }else { Add(P,psz-1) }
        }else {
            if(msz>=2){
                Add(M,msz-1) Add(M,msz-2)
            }else ans[sz++] = pzero;
        }
    }

    sort(ans,ans+sz);
    printf("%d\n%d",sz,ans[0]);
    for(int i = 1; i < sz; i++) printf(" %d",ans[i]);
    putchar('\n');
    return 0;
}

 

posted @ 2015-08-04 22:36  陈瑞宇  阅读(367)  评论(0编辑  收藏  举报