50pts正解求调(已过所有大样例)
查看原帖
50pts正解求调(已过所有大样例)
341091
End_Sunset楼主2024/10/29 19:29

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";
	}
} 
2024/10/29 19:29
加载中...