题面:给定大小为n的数组A,大小为m的数组B,那么共有n*m个元素和。现给出L对禁用下标(a,b),找一对不在L中的下标(i,j),使用A[i]+B[j]最大,求该最大值。
范围:n,m<=1e5; 1<=L<=min(1e5,nm-1)
思路:先对A和B按从大到小排序,然后让i指向A起始位置,j指向B起始位置,将对应的四元组(sum,i,j,flag)加入优先队列,初始为(A[0]+B[0],0,0,1)。对于从优先队列弹出的元素:
1、如果(i,j)不在L内,则对应的sum为答案。
2、否则进行扩展,(i,j) -> (i,j+1)固定要做,如果flag=1,则额外做(i,j) -> (i+1,j)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a; i<=b; i++)
#define per(i,a,b) for(int i=b; i>=a; i--)
const int N = 100005;
int n, m, L;
vector<pair<int,int>> va, vb;
set<pair<int,int>> forbid;
void solve() {
cin >> n >> m >> L;
rep(i,1,n) {
int x;
cin >> x;
va.push_back({x,i});
}
rep(i,1,m) {
int x;
cin >> x;
vb.push_back({x,i});
}
rep(i,1,L) {
int c, d;
cin >> c >> d;
forbid.insert({c,d});
}
sort(va.rbegin(), va.rend());
sort(vb.rbegin(), vb.rend());
priority_queue<tuple<int,int,int,int>> q;
q.push({va[0].first+vb[0].first, 0, 0, 1});
while (!q.empty()) {
auto [v,i,j,f] = q.top(); q.pop();
if (forbid.count({va[i].second,vb[j].second}) == 0) {
cout << v << "\n";
return;
}
if (i < n && f) q.push({va[i+1].first+vb[j].first, i+1, j, 1});
if (j < m) q.push({va[i].first+vb[j+1].first, i, j+1, 0});
}
}
signed main() {
cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
标签:va,vb,int,rep,元素,cin,abc331E,forbid,数组
From: https://www.cnblogs.com/chenfy27/p/18060745