1 条题解
-
0
题目理解
有 个人,排名 到 。主办方有 条列入标准,然后依次处理每条标准:就让排名最靠前且没有被列过的的 个列入(如果不够,有多少列多少)。有些人会拒绝,然后就在算拒绝之后的答案。
代码思路
说白了,就是用贪心模拟列入过程。
:满足标准 的所有人排名,按排名从小到大存储。
: 当前被哪个标准列入( 表示没有邀)。
:标准 已经用到了 中的第几个人。
:标记 是否拒绝( 表示拒绝)。
初始列入:
从标准 到 依次处理,对每个标准 ,从 中依次取没有邀的人(跳过已邀的),直到取满 个或列表结束。被邀人的排名加入答案 。
处理拒绝:
就按顺序依次让人 拒绝。
如果 之前被列入标准里(),先从答案中减去 ,然后从原标准 开始,把别人列入准(调用 dfs() )。
dfs():从标准 的当前没有选位置 tot[i] 往后找,找到第一个没有被拒绝()且可以获得的人 。
-
如果 不在任何标准里,直接将他列于此标准,更新 ,答案加上 ,结束。
-
如果 在其他标准 存在,且 (即优先级更低的标准),则让标准 重新找一个替补(递归 dfs()),然后把 拿过来,更新 ,结束。
-
如果( 或 )跳过该人,继续往后找。
这样保证每次算完后,结果仍满足顺序。
代码
#include<bits/stdc++.h> #define int long long using namespace std; int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return x*f; } const int N=100005; int a[N],f[N],viss[N],ans,vis[N],tot[N],bl[N]; vector<int>ve[N]; void dfs(int x){ while(tot[x]<(int)ve[x].size()){ int t=ve[x][tot[x]]; if(!vis[t]){ if(!bl[t]){ tot[x]++; ans+=t; bl[t]=x; break; } if(bl[t]>x){ dfs(bl[t]); bl[t]=x;break; } } tot[x]++; } return; } signed main(){ int n=read(),m=read(); for(int i=1;i<=m;i++)f[i]=read(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=n;i++){ int h=read(); for(int j=1;j<=h;j++)ve[read()].push_back(i); } for(int i=1;i<=m;i++){ int k=0; for(;tot[i]<(int)ve[i].size()&&k<f[i];tot[i]++){ int h=ve[i][tot[i]]; if(!bl[h]){ ans+=h;k++;bl[h]=i; } } } cout<<ans<<"\n"; for(int i=1;i<n;i++){ vis[a[i]]=1; if(bl[a[i]]){ ans-=a[i]; dfs(bl[a[i]]); } cout<<ans<<"\n"; } }时间复杂度:
完结撒花!
-
- 1
信息
- ID
- 3009
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 12
- 已通过
- 6
- 上传者