abc331E 两数组元素间带限制的最大和

题面:给定大小为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;
}
posted @ 2024-03-08 12:37  chenfy27  阅读(4)  评论(0编辑  收藏  举报