D. Data Center(2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest)

D. Data Center
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

The startup "Booble" has shown explosive growth and now it needs a new data center with the capacity ofm petabytes. Booble can buy servers, there aren servers available for purchase: they have equal price but different capacities. Thei-th server can storeai petabytes of data. Also they have different energy consumption — some servers arelow voltage and other servers are not.

Booble wants to buy the minimum number of servers with the total capacity of at leastm petabytes. If there are many ways to do it Booble wants to choose a way to maximize the number oflow voltage servers. Booble doesn't care about exact total capacity, the only requirement is to make it at leastm petabytes.

Input

The first line contains two integer numbers n andm (1 ≤ n ≤ 2·105, 1 ≤ m ≤ 2·1015) — the number of servers and the required total capacity.

The following n lines describe the servers, one server per line. Thei-th line contains two integersai,li (1 ≤ ai ≤ 1010, 0 ≤ li ≤ 1), whereai is the capacity,li = 1 if server islow voltage andli = 0 in the opposite case.

It is guaranteed that the sum of all ai is at leastm.

Output

Print two integers r and w on the first line — the minimum number of servers needed to satisfy the capacity requirement and maximum number oflow voltage servers that can be bought in an optimalr servers set.

Print on the second line r distinct integers between 1 andn — the indices of servers to buy. You may print the indices in any order. If there are many solutions, print any of them.

Sample test(s)
Input
4 10
3 1
7 0
5 1
4 1
Output
2 1
4 2
Input
3 13
6 1
6 1
6 1
Output
3 3
1 2 3 
Note

In the first example any pair of servers which includes the server 2 is a correct output.


分析:贪心。首先找出最少的数量k,就是按照data从大到小排序,然后累加到大于m即可。然后对1和0对应的数据data和下标用两个数组存起来,并按data从大到小排序,

            分两种情况考虑:

            如果 1 的数量 >= k ,那么先将 1 的 data 累加 k个得到总数 cnt ,如果 cnt < m,那么就用 0 的从大到小依次替换 已经累加的1 中最小的值,直到cnt >= m。

            如果 1 的数量 < k,那么先将 1 的data全部加起来,再加上 0 的data 直到数量达到 k,如果cnt < m,那么继续用 0 的替换 已经累加的1 中最小的值,直到 cnt >= m。

题目链接:http://codeforces.com/gym/100513/problem/D

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
struct edge{
    int pose;
    ll data;
}b[200005],c[200005];

bool cmp(edge a,edge b){
    return a.data>b.data;
}

int n,q,ans[200005];
ll m,p,a[200005];
int main(){
    int bb=0,cc=0;
    scanf("%d%I64d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%I64d%d",&p,&q);
        a[i]=p;
        if(q==1){
            b[bb].data=p;
            b[bb].pose=i;
            bb++;
        }
        else{
            c[cc].data=p;
            c[cc].pose=i;
            cc++;
        }
    }
    sort(a,a+n);
    ll sum=0,k=0;
    for(int i=n-1;i>=0;i--){ //求出最少的数量 k 
        sum+=a[i];
        k++;
        if(sum>=m) break;
    }
    sort(b,b+bb,cmp);
    sort(c,c+cc,cmp);
    int pos=0,pp;
    if(bb>=k){      
        ll cnt=0;
        pp=k;
        for(int i=0;i<k;i++){
            cnt+=b[i].data;
            ans[pos++]=b[i].pose;
        }
        if(cnt<m){    
            int tt=k-1;
            for(int i=0;i<cc;i++){     //依次替换已经累加的“1”的最小值,直到cnt>=m
                cnt=cnt-b[tt].data+c[i].data;
                ans[tt]=c[i].pose;
                tt--;
                pp--;
                if(cnt>=m) break;
            }
        }
    }
    else{
        ll cnt=0; pp=bb;
        for(int i=0;i<bb;i++){
            cnt+=b[i].data;
            ans[pos++]=b[i].pose;
        }
        for(int i=0;i<k-bb;i++){
            cnt+=c[i].data;
            ans[pos++]=c[i].pose;
        }
        if(cnt<m){
            int tt=bb-1;
            for(int i=k-bb;i<cc;i++){      //依次替换已经累加的“1”的最小值,直到cnt>=m
                cnt=cnt-b[tt].data+c[i].data;
                ans[tt]=c[i].pose;
                tt--;
                pp--;
                if(cnt>=m) break;
            }
        }
    }
    printf("%d %d\n",pos,pp);
    for(int i=0;i<pos;i++){
        if(i) printf(" ");
        printf("%d",ans[i]+1);
    }
    printf("\n");
    return 0;
}


你可能感兴趣的:(ACM,codeforces,贪心)