An interesting question --- sort of thinking, enumerate

 

  This question is on the way to school brother to eat school brother say listen, I feel quite interesting, requires a lot of thinking (I may not have time to brush the question, and a little stupid the ~)

  Hereby record it:

 

 Problem:

    There are n (x, y) tuple, remove the request from the k-tuples such that x of the k-tuples multiplied by the largest value (sum (x) * min is the minimum value of y (y) in k tuple)

 

 Solution:

    N-tuples sorted by ascending y value, then small to large enumeration each y value, the minimum value of the current value of y is selected tuples of k, then the k-tuple in the current tuple after the (constant current comprising tuple). That is, there tuples k-1 has not been determined, it is necessary to select the k-1 corresponding to the maximum value of x after the current tuple from the tuple. So the problem is reduced to the current tuple to take the k-1 maximum number. Calculated sum_i (x) * min_i (y), i is the index of the current tuple, the maximum value is the correct answer.

    In order to increase the speed of transfer of enumeration, we maintain a set of two-tuple i + 1-n of the maximum of the k-1 and x. set2 stored in the k-1 greatest X, set1 stored in the remaining x (index = i + 1 ~ n-tuples), so the transfer time necessary to determine a tuple [i + 1] .x whether the set1, in directly removed; set2 in otherwise constant, the need to eliminate it, and remove from the largest x set1, of course, after removing the need to eliminate set1 x.

 

 code show as below:

#include <the iostream> 
#include <algorithm> 
#include < String > 
#include < SET >
 the using  namespace STD;
 // Problem: There are n (x, y) tuple, remove the request from the k-tuples, so that k the tuple x and y is multiplied by the smallest value of the maximum value (sum (x) * min ( y) in k tuples)
 // Solution: n-tuples sorted by ascending y values, then ascending enumeration each y value, the minimum value of the current value of y is selected tuples of k, then the k-tuples is located after the current tuple (a tuple must contain current). That
 //             There tuples k-1 has not been determined, it is necessary to select the k-1 corresponding to the maximum value of x after the current tuple from the tuple. So the problem is reduced to the current tuple to take the k-1 maximum number. Calculated sum_i (x) * min_i (y ), i is the current tuple
 //           index, takes the maximum value is the correct answer.
@             In order to improve the transfer speed of the enumeration, we maintain a set of two-tuple i + 1-n of the maximum of the k-1 and x. set2 stored in the k-1 greatest x, set1 stored in the remaining x (index = i + 1 ~ n tuples), so transferred
 //            Determining when needed tuple [i + 1] .x whether set1, the directly removed; set2 in otherwise constant, the need to eliminate it, and remove from the largest x set1, of course, after removing the need to eliminate set1 x. 
const  int N = 1E5 + . 5 ; 
typedef pair < int , int > Tuple;
 BOOL CMP ( const Tuple A, const Tuple B) {
     return a.second < b.second; 
} 
multiset < int > S1, S2; 
multiset < int > :: Iterator IT; 
multiset < int > :: a reverse_iterator RIT; 

int main () 
{
    int n, k; cin >> n >> k;
    Tuple data[N];
    for (int i = 0; i < n; i++) {
        cin >> data[i].first >> data[i].second;
    }
    sort(data, data + n, cmp);
    for (int i = 1; i < n; i++) {
        s1.insert(data[i].first);
    }
    int ans = 0;
    int sum = 0;
    for (int i = 1; i < k; i++) {
        int max_val = *s1.rbegin();
        s1.erase(s1.find(max_val));
        s2.insert(max_val);
        sum += max_val;
    }
    for (int i = 0; i +k-1< n; i++) {
        ans = max(ans, data[i].second*(sum+data[i].first));
        if (n - i == k) break;
        if (s1.count(data[i+1].first) >0) {
            it = s1.find(data[i+1].first);
            s1.erase(it);
        }
        else {
            it = s2.find(data[i+1].first);
            sum -= *it;
            s2.erase(it);

            rit = s1.rbegin();
            sum += *rit;
            s2.insert(*rit);
            s1.erase(s1.find(*rit));
        }
    }
    std::cout << "Answer = " << ans << endl;
    return 0;
}

/*
5 2
2 3
4 1
5 7
1 3
6 3
*/

 

Guess you like

Origin www.cnblogs.com/chen9510/p/11613849.html