TLE 60pts复杂度正确求卡常
查看原帖
TLE 60pts复杂度正确求卡常
684960
Solwek楼主2024/11/8 18:04

RT,n105n\le 10^5 的点都过不去,时间复杂度 O(r(n+v))O(r(n+v))

#include<bits/stdc++.h>
using namespace std;

const int N=200005;
bool f[105][N],s[105][N],ans[105][N];
vector<int>vs[N];
int l[N],r[N],id[N],ps[N],tr[N],v[N],vis[N],cnt[N];
int pos;
void solve(){
	for(int i=1;i<=200000;i++){
		vs[i].clear();
		l[i]=0;r[i]=0;
		id[i]=0;v[i]=0;
		tr[i]=0;cnt[i]=0;
		ps[i]=0;vis[i]=0;
	}
	memset(f,0,sizeof(f));
	memset(s,0,sizeof(s));
	memset(ans,0,sizeof(ans));
	int n,k,q;
	cin>>n>>k>>q;
	pos=0;
	int mx=0;
	for(int i=1;i<=n;i++){
		int len;
		cin>>len;
		int lx=pos+1,rx=pos+len;
		for(int j=1;j<=len;j++){
			pos++;
			cin>>v[pos];
			l[pos]=lx,r[pos]=rx;
			id[pos]=i;
			vs[v[pos]].push_back(pos);
			mx=max(mx,v[pos]);
		}
	}
	for(int i=1;i<=pos;i++){
		if(v[i]==1){
			int rx=min(r[i],i+k-1);
			tr[i+1]++;
			tr[rx+1]--;
		}
	}
	for(int i=1;i<=pos;i++)tr[i]+=tr[i-1];
	for(int i=1;i<=pos;i++){
		if(tr[i]>=1)
			f[1][i]=1,ans[1][v[i]]=1;
	}
	for(int i=2;i<=100;i++){
		for(int j=1;j<=pos;j++)tr[j]=0;
		for(int j=1;j<=mx;j++){
			for(auto k:vs[j]){
				s[i][j]|=f[i-1][k];
				if(f[i-1][k]&&!vis[id[k]]){
					vis[id[k]]=1;
					ps[j]=id[k];
					cnt[j]++;
				}
				if(cnt[j]>=2)break;
			}
			for(auto k:vs[j])vis[id[k]]=0;
		}
		for(int j=1;j<=pos;j++){
			int x=v[j],rx=min(j+k-1,r[j]);
			if(s[i][x]){
				if(cnt[x]>=2){
					tr[j+1]++;
					tr[rx+1]--;
				}else if(cnt[x]==1&&ps[x]!=id[j]){
					tr[j+1]++;
					tr[rx+1]--;
				}
			}
		}
		for(int j=1;j<=pos;j++)tr[j]+=tr[j-1];
		for(int j=1;j<=pos;j++){
			int x=tr[j];
			if(x>=1)f[i][j]=1,ans[i][v[j]]=1;
			else f[i][j]=0;
		}
		for(int j=1;j<=mx;j++)cnt[j]=0,ps[j]=0;
	}
	while(q--){
		int x,y;
		cin>>x>>y;
		cout<<ans[x][y]<<'\n';
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T;
	cin>>T;
	while(T--)
		solve();
	return 0;
}
2024/11/8 18:04
加载中...