Problem:
Score : 500 points

Problem Statement

Given are N integers A_1,\ldots,A_N.

We will choose exactly K of these elements. Find the maximum possible product of the chosen elements.

Then, print the maximum product modulo (10^9+7), using an integer between 0 and 10^9+6 (inclusive).

Constraints

1 \leq K \leq N \leq 2\times 10^5

|A_i| \leq 10^9

Input

Input is given from Standard Input in the following format:

N K
A_1 \ldots A_N

Output

Print the maximum product modulo (10^9+7), using an integer between 0 and 10^9+6 (inclusive).

Sample Input 1

4 2
1 2 -3 -4

Sample Output 1

12

The possible products of the two chosen elements are 2, -3, -4, -6, -8, and 12, so the maximum product is 12.

Sample Input 2

4 3
-1 -2 -3 -4

Sample Output 2

1000000001

The possible products of the three chosen elements are -24, -12, -8, and -6, so the maximum product is -6.

We print this value modulo (10^9+7), that is, 1000000001.

Sample Input 3

2 1
-1 1000000000

Sample Output 3

1000000000

The possible products of the one chosen element are -1 and 1000000000, so the maximum product is 1000000000.

Sample Input 4

10 10
1000000000 100000000 10000000 1000000 100000 10000 1000 100 10 1

Sample Output 4

999983200

Be sure to print the product modulo (10^9+7).

Solution in C++ (GCC 9.2.1) (judge verdict: Runtime Error)

#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"

using namespace std;
using namespace __gnu_pbds;


#define ll long long int
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define all(a) a.begin(),a.end()

typedef tree <ll, null_type, less <ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// order_of_key(val): returns the number of values less than val
// find_by_order(k): returns an iterator to the kth largest element (0-based)
ll mod = 1e9 + 7;
ll power(ll x, ll y) {
	ll ans = 1;
	while(y) {
		if(y & 1) {
			ans = (ans * x) % mod;
		}
		if(ans < 0) {
			ans += mod;
		}
		x = (x * x) % mod;
		y /= 2;
	}
	return ans;
}
ll modinverse(ll x) {
	return power(x, mod - 2);
}
int main(void)
{
	ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll n, k, ans, tot = 1, l;
    cin >> n >> k;
    ll a[n], i;
    vector<ll> pos, neg, zer, pos2, neg2, zero;
    for(i = 0; i < n; i++) {
    	cin >> a[i];
    	if(a[i] > 0) {
    		pos.pb(a[i]);
    	} else if(a[i] < 0) {
    		neg.pb(a[i]);
    	} else {
    		zero.pb(a[i]);
    	}
    	tot = (tot * a[i]) % mod;
    	if(tot < 0) {
    		tot += mod;
    	}
    }
    if(k == n) {
    	cout << tot << "\n";
    	return 0;
    }
    sort(pos.rbegin(), pos.rend());
    sort(all(neg));
    pos2 = pos;
    neg2 = neg;
    for(i = 1; i < pos.size(); i++) {
    	pos[i] = (pos[i] * pos[i-1])%mod;
    }
    neg[0] = neg[0] % mod;
    if(neg[0] < mod) {
    	neg[0] += mod;
    }
    for(i = 1; i < neg.size(); i++) {
    	neg[i] = (neg[i] * neg[i-1])%mod;
    	if(neg[i] < 0) {
    		neg[i] += mod;
    	}
    }
    if(neg.size() == 0) {
    	if(pos.size() < k) {
    		cout << "0\n";
    	} else {
    		cout << pos[k-1] << "\n";
    	}
    	return 0;
    }
    if(pos.size() == 0) {
    	if(k & 1) {
    		if(zero.size() == 0) {
    			ans = (neg[n-1] * modinverse(neg[n - k - 1]))%mod;
    			if(ans < 0) {
    				ans += mod;
    			}
    			cout << ans << "\n";
    		} else {
    			cout << "0\n";
    		}
    	} else {
    		if(neg.size() < k) {
    			cout << "0\n";
    		} else {
    			cout << neg[k-1] << "\n";
    		}
    	}
    	return 0;
    }
    if(pos.size() < k) {
    	cout << "HERE\n";
    	if(pos.size() + neg.size() < k) {
    		cout << "0\n";
    		return 0;
    	} else if(pos.size() + neg.size() == k) {
    		if(k == n) {
    			cout << tot << "\n";
    		} else {
    			if(neg.size() & 1) {
    				cout << "0\n";
    			} else {
    				ll ans = (pos.back() * neg.back())%mod;
    				if(ans < 0) {
    					ans += mod;
    				}
    				cout << ans << '\n';
    			}
    		}
    		return 0;
    	} else {
   //  		ll l = 0, f = 0, n = 0, con = 0;
   //  		ll n1 = pos.size();
   //  		ll n2 = neg.size();
   //  		ans = 1;
   //  		while(con < k) {
   //  			if((l < n1) && (f >= n2 || pos2[l] >= (-neg2[f]))) {
   //  				ans = (ans * pos2[l++]) % mod;
   //  			} else {
   //  				n++;
   //  				ans = (ans * (neg2[f++])) % mod;
   //  				if(ans < 0) {
   //  					ans += mod;
   //  				}
   //  			}
   //  			con++;
   //  		}
			// if(n & 1) {
			// 	if(l < n1 && f < n1) {
			// 		ll ans1, ans2;
			// 		if(f == 1) {
			// 			ans1 = 1;
			// 		} else {
			// 			ans1 = -neg2[f-2];
			// 		}
			// 		if(l == 1) {
			// 			ans2 = 1;
			// 		} else {
			// 			ans2 = pos2[f-2];
			// 		}
			// 		ans1 = ans1 * pos2[l];
			// 		ans2 = ans2 * abs(neg2[f]);
			// 		if(ans1 > ans2) {
			// 			ans = (ans * modinverse(neg2[f-1]))%mod;
			// 			ans = (ans * pos2[l]) % mod;
			// 			if(ans < 0) {
			// 			ans += mod;
			// 			}
			// 		} else {
			// 			ans = (ans * modinverse(pos2[l-1])) % mod;
			// 			ans = (ans * neg2[f]) % mod;
			// 		}
			// 	} else if(l < n1) {
			// 		ans = (ans * modinverse(neg2[f-1]))%mod;
			// 		ans = (ans * pos2[l]) % mod;
			// 		if(ans < 0) {
			// 			ans += mod;
			// 		}
			// 	} else {
			// 		ans = (ans * modinverse(pos2[l-1])) % mod;
			// 		ans = (ans * neg2[f]) % mod; 
			// 	}
			// }
   //  		cout << ans << "\n";
   //  	}
	    	ll take = pos.size() - 1;
	    	ll left = k - pos.size();
	    	if(left & 1) {
	    		take--;
	    		left++;
	    	}
	    	ans = (pos[take] * neg[left - 1]) % mod;
	    	i = take;
	    	l = left;
	    	goto here;
	    }
    }
    ans = pos[k-1];
    l = 0, i = k - 1;
    here:;
    n = neg.size();
    for(; i > 0; i-=2) {
    	if(l >= n - 1) {
    		break;
    	}
    	ll cur1 = pos2[i] * pos2[i - 1];
    	ll cur2 = neg2[l] * neg2[l + 1];
    	if(cur1 >= cur2) {
    		break;
    	}
    	ans = (ans * modinverse(cur1)) % mod;
    	ans = (ans * cur2) % mod;
    	if(ans < 0) {
    		ans += mod;
    	}
    	l += 2;
    }
    cout << ans << '\n';
}