第三场 2025 钉耙编程春季联赛 补题 1003
题意
给定一个人的初始 \(m\) 维能力 , 以及 \(n\) 个 \(m\) 维数组 , 求是否存在一个排列
使得每一维能力值大于等于数组的能力值 , 在通过此次数组后 , 初始能力值相应提升一定值
思路
先考虑朴素的暴力解法 , 每次扫描当前所有数组 , 然后选可以选的 , 再对初始值进行更新 , 重复操作直到无法操作或者全部操作
这个时候发现 , 暴力解法之所以慢 , 就是因为浪费时间在查找哪些新增公司可以面试
如何快速找到可以面试的新公司呢?
我们将某一个维度的公司需求进行排序 , 在增加能力值后某些能力值会低于当前能力值 , 此时找到这些能力值对应的公司即可
另外开一个记录每个公司不足的数组 , 每当达到了某一维度标准 , 就让其减一 , 当为零时就可以去面试这个公司了
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long int
typedef pair<int,int> PII;
inline int read() {
int ans = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
ans = ans * 10 + ch - '0';
ch = getchar();
}
return ans * f;
}
void solve() {
int n =read() , m=read();
vector<int> a(m+1);
for (int i =1; i<= m; i++) {
a[i] = read();
}
vector<vector<int>>c(n+1,vector<int>(m+1));
vector<vector<int>>w(n+1,vector<int>(m+1));
for (int i = 1; i<= n; i++) {
for (int j = 1; j <= m; j++) {
c[i][j] =read();
}
for (int j = 1; j<= m; j++) {
w[i][j] = read();
}
}
int ca[n+1] = {0};
priority_queue<PII,vector<PII>,greater<PII>> pq[m+1];
queue<int>q;
for (int i =1 ; i<= n; i++) {
bool f= true;
for (int j = 1; j<= m; j++) {
if (c[i][j] > a[j]) {
f = false;
ca[i]++;
pq[j].push({c[i][j],i});
}
}
if (f) {
q.push(i);
}
}
while (q.size()) {
auto u = q.front();
q.pop();
for (int i = 1; i<= m; i++) {
a[i] += w[u][i];
while( pq[i].size()&& a[i] >= pq[i].top().first) {
auto v = pq[i].top();
pq[i].pop();
ca[v.second]--;
if (ca[v.second] == 0) {
q.push(v.second);
}
}
}
}
for (int i =1; i<= n; i++) {
if (ca[i]) {
cout<<"NO\n";
return ;
}
}
cout<<"YES\n";
// return ;
}
signed main() {
int t= read();
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号