1 条题解
-
0
自动搬运
来自洛谷,原作者为

CashCollectFactory
这个家伙不懒,但什么都留下了搬运于
2025-08-24 22:49:33,当前版本为作者最后更新于2023-11-23 22:10:42,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题目大意
公司里有多种员工,每种员工数量已知。现在有若干个工程待完成,完成每项工程都对各类员工的数目有一定最低要求,且完成每项工程后都会获得一定数目新员工的奖励。求能完成的最多工程数。
题目分析
由于员工不是消耗品,显然越多越好,且获得员工的时机并不影响以后工程的完成,因此该问题显然满足无后效性。那么贪心算法就已经呼之欲出了!我们只要不停的遍历所有工程,遇到可完成的就直接完成并累加员工数,当任何工程都无法完成时,则输出已完成的工程数,最终的时间复杂度为 。面对十的五次方规模的数据,显然难以忍受。接下来考虑优化!
解法优化
标签思想是 OI 界的重要思想之一,本题更是体现的淋漓尽致。观察到保证 与 之和均不超过 ,我们应当以此为着手点进行代码迭代,发力数据规模痛点,对题目需求进行归因分析,从而打出一套组合拳,完成对此题目的降维打击!
具体而言,我们为每一个员工类型开一个标签,数组用于维护这些标签,标签中则存储所有对该类员工有需求的工程序号与需求数量。当该类员工数值有所更新时,在维护得到已达到的为需求数目。此外,我们还需要一个计数数组来记录每个工程的待满足需求数,当待满足要求数为零时,说明该工程已可实施,则可将其放入一个栈或队列中,从而通过维护这个栈或队列来统计答案。注意到 ,我们难以开如此巨大的数组,所以考虑离散化或
unorder_map。 最终复杂度为 ,采用离散化的话则是 ,其他具体的实现细节可以移步代码实现,里边的注释还是挺详细的!代码实现
#include<bits/stdc++.h> using namespace std; struct tagy{ int gongcid,wnum; bool operator < (const tagy &x) const { return (wnum==x.wnum) ? gongcid<x.gongcid : wnum<x.wnum; }//注意这里的小于号重载 tagy(int G,int W){ gongcid=G,wnum=W; } }; //构建一个标签结构体,分别记录各个工程序号及需求员工数量。 struct rwd{ int kd,nm; rwd(int K,int N){ kd=K,nm=N; } }; //构建一个奖励结构体,用于在处理可实施工程时候更新员工数量。 int n,m,tn1,tn2,ans; int cnt[500005];//记录每个工程的待满足需求量 unordered_map<int,int> ar; //记录每种员工目前的数量 stack<int> s;//维护目前可实施的全部工程 map<int,set<tagy> > tgm; vector<rwd> v[500005]; int main(){ scanf("%d",&n); while(n--){ scanf("%d%d",&tn1,&tn2); ar[tn1]=tn2; } scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d",&n); int t=0; while(n--){ scanf("%d%d",&tn1,&tn2); if(ar[tn1]>=tn2) continue; //若已满足,则忽略。 tgm[tn1].insert(tagy(i,tn2)); t++; } if(!t) s.push(i); cnt[i]=t; scanf("%d",&n); while(n--){ scanf("%d%d",&tn1,&tn2); v[i].push_back(rwd(tn1,tn2)); } } while(s.size()){ ans++; n=s.top(); s.pop(); for(int i=0;i<v[n].size();i++){ ar[v[n][i].kd]+=v[n][i].nm; while(1){ if(tgm[v[n][i].kd].size()==0) break; set<tagy>::iterator IT; IT=tgm[v[n][i].kd].begin(); if((IT->wnum) > ar[v[n][i].kd]) break; cnt[IT->gongcid]--; if(cnt[IT->gongcid]==0) s.push(IT->gongcid); tgm[v[n][i].kd].erase(IT); } } } cout<<ans; return 0; }需要注意的是,本参考代码使用了 unordered_map,因此需要 C++11 及以上版本。
(
PS.记得雁过留声啊)
- 1
信息
- ID
- 9092
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者