题解:P11088 [ROI 2021 Day 1] 穿孔卡片
Hollow_knight_ · · 题解
尝试贪心地依次选择能放在当前最上面的卡片。即先选择最上面的卡片,然后次上层,次次上层......
显然,卡片
于是记
假设放置了第一张卡片
具体地,若卡片
那么可以提前对于所有字符串下标
此时遍历卡片
若更新完有
同时记录指针
若存在某一时刻
若存在某一时刻
对于遍历每个位置,时间复杂度为
对于遍历所有
总时间复杂度
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+15;
int n,m,hd=1,tl,q[N],vist[N],visp[N],f[N];//vist[i]:卡片i是否被使用 visp[i]:位置i是否被覆盖
vector<int>ans,p[N],g[N];//p[i]:卡片i覆盖的位置 g[i]:意义见题解
char c,s[N];
int main(){
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for(int k,j,i=1;i<=n;++i){
scanf("%d",&k);
while(k--){
scanf("%d %c",&j,&c);
p[i].push_back(j);
if(s[j]!=c)++f[i],g[j].push_back(i);//模拟
}
if(!f[i])q[++tl]=i;//模拟
}
int cnt=m;
for(int w;hd<=tl;){
ans.push_back(w=q[hd++]),vist[w]=true;//取出一个f值为0的卡片w
for(int i:p[w]){
if(visp[i]==true)continue;
--cnt,visp[i]=true;//遍历w覆盖的所有位置
for(int j:g[i]){
if(!--f[j])q[++tl]=j;//更新
}
}
if(!cnt){
for(int i=1;i<=n;++i){if(!vist[i])ans.push_back(i);}
for(int i:ans)printf("%d ",i);
return 0;
}
}
printf("-1");//(cnt!=0 && q.empty()==true)
return 0;
}