rt,与第二篇题解做法惊人地相似,类BFS做法
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
#define pii pair<int,int>
#define fst first
#define scd second
int n,K,q;
int s[N],num[N],st[N],vis[N],ans[N],lst[N];
pair<pii,int> qry[N];
int main(){
// freopen("chain6.in","r",stdin);
// freopen("chain.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int T; cin>>T;
while(T--){
for(int i=0; i<=2e5; i++) num[i]=-1,lst[i]=-2e9;
memset(vis,0,sizeof(vis)); //多测清空
cin>>n>>K>>q;
int m=1,cur=1;
for(int i=1; i<=n; i++) {
int l; cin>>l; st[i]=m; //[st[i],st[i+1])为第i个人的序列区间
for(; m<st[i]+l; m++) cin>>s[m];
}
st[n+1]=m+1;
for(int i=1; i<=m; i++) vis[i]=(s[i]==1);
for(int i=1; i<=q; i++) cin>>qry[i].fst.fst>>qry[i].fst.scd,qry[i].scd=i;
sort(qry+1,qry+q+1); //将询问离线,按照r[i]排序
for(int i=1; i<=qry[q].fst.fst; i++){
for(int j=1,k=1; j<=m; k+=(st[k+1]<=(++j))){
if(j+1!=st[k+1]) lst[j]=((vis[j]) ? j : lst[j-1]);
vis[j]=(st[k]!=j&&lst[j-1]+K>j);
}
//此时vis[j]代表Round i时j能否作龙尾
for(int j=1; j<=m; j++) num[s[j]]=-1;
for(int j=1,k=1; j<=m; k+=(st[k+1]<=(++j))){
if(!vis[j]) continue;
if(num[s[j]]==-1) num[s[j]]=k;
if(num[s[j]]!=k) num[s[j]]=0;
}
//num[i]记录以数i为结尾的有哪些人(-1无 / 0多个人)
for( ;qry[cur].fst.fst==i && cur<=q; cur++)
ans[qry[cur].scd]=(num[qry[cur].fst.scd]!=-1); //cur代表当前询问,存在以数i结尾的人时为true
for(int j=1,k=1; j<=m; k+=(st[k+1]<=(++j))) vis[j]=(num[s[j]]!=-1&&num[s[j]]!=k);
//此时vis[j]代表Round i+1时j能否作龙头
}
for(int i=1; i<=q; i++) cout<<ans[i]<<"\n";
}
}