Codeforces Round #744 (Div. 3)
题意
给一个长度为n的数组a,求最多有几个组合 ( i d x i , i d x j ) , 满 足 i ≠ j 且 1 ≤ i , j ≤ n (idx_i , idx_j),满足 i \neq j且1\leq i, j \leq n (idxi,idxj),满足i=j且1≤i,j≤n。每个下标最多被使用 a i a_i ai次。
思路
将所有非零的数值存入优先队列中,每次选则数量最大与次大的两个值进行交谈,每次交谈过后要及时进行出队入队操作。
(我开始是这样想的:每次对最小的和最大的进行操作,可是。。我实现不了)
代码
思路简单,代码也简单。简简单单40行。
#include<cstdio>
#include<deque>
#include<queue>
#include<set>
#include<cstdlib>
#include<string.h>
#include<string>
#include<iostream>
#include<cmath>
#include<unordered_map>
#include<map>
#include<algorithm>
#define endl "\n"
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
#define ft first
#define sd second
#define pll pair<ll, ll>
#define pii pair<int, int>
#define ll long long int
#define ull unsigned long long int
#define mt(a,b) memset(a, b, sizeof a)
//#define int long long
const double PI = acos(-1.0);
const int inf = 0x3f3f3f3f;
const int INF = 0x7fffffff;
using namespace std;
const int N = 2e5 + 7, M = 1e6 + 10;
priority_queue<pii>q;
pii s[N];
pii ans[M];
int main()
{
IOS;
int t; cin >> t;
while (t--)
{
int n; cin >> n;
while (!q.empty()) q.pop();//注意及时清空队列
for (int i = 1; i <= n; i++)
{
cin >> s[i].ft, s[i].sd = i;
if (s[i].ft) q.push(s[i]);//可以直接进行make_pair,而不必要开s数组
}
int k = 0;
while (q.size() >= 2)
{
pii a = q.top(); q.pop();//最大
pii b = q.top(); q.pop();//次大
ans[++k].ft = a.sd;
ans[k].sd = b.sd;
if (--a.ft)q.push(make_pair(a.ft, a.sd));//非零
if (--b.ft)q.push(make_pair(b.ft, b.sd));//非零
}
cout << k << endl;
for (int i = 1; i <= k; i++)
{
if (ans[i].ft > ans[i].sd) swap(ans[i].ft, ans[i].sd);
cout << ans[i].ft << " " << ans[i].sd << endl;
}
}
return 0;
}