可能是小问题
查看原帖
可能是小问题
131591
蒟蒻君HJT泽渡透香楼主2022/4/11 17:37

#7-10 TLE 已经修改了写法,用topsort找环,可是发现在solve()函数中,这几行:

for(int i=1;i<=ntot;++i){
		for(int j=head[i];j;j=nxt[j]){
			++rd[ver[j]];
		}
	}

跑的非常慢,#7的第一个点,本人输出中间结果发现边数(tot)和点数(ntot)在1e6左右并不大,在二分debug的时候确定了是这几行非常慢,不是其他的地方,请问这是为什么呢?实在不能理解

#include <bits/stdc++.h>
using namespace std;
void solve();
void init(); 
inline int read(){
	int x=0;char c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9')x=x*10+(c-'0'),c=getchar();
	return x;
}
int main(){
	int T;init();
	freopen("string7.in","r",stdin);
	scanf("%d",&T);
	while(T--) solve();
	return 0;
}
char s[200005];
int n;
int rk[400005],sa[400005],old[400005],tp[400005],bag[400005],m,hi[200005];
int rmq[200005][20],lg[200005];
void init(){
	int now=0;
	for(int i=1;i<=200000;++i){
		lg[i]=now;
		if((1<<now+1)==i) ++now;
	}
	return ;
}
int lcp(int x,int y){
	if(x==y) return rmq[x][0];
	int l=y-x;
	return min(rmq[x+1][lg[l]],rmq[y-(1<<lg[l])+1][lg[l]]);
}
void get_sa(){
	m=max(300,n);
	memset(bag,0,sizeof bag);
	for(int i=1;i<=n;++i) rk[i]=s[i],++bag[rk[i]];
	for(int i=1;i<=m;++i) bag[i]+=bag[i-1];
	for(int i=n;i>=1;--i) sa[bag[rk[i]]--]=i;
	for(int w=1,p;;w<<=1){
		p=0;
		for(int i=1;i<=m;++i) bag[i]=0; 
		for(int i=n-w+1;i<=n;++i) tp[++p]=i;
		for(int i=1;i<=n;++i) if(sa[i]>w) tp[++p]=sa[i]-w;
		for(int i=1;i<=n;++i) ++bag[rk[tp[i]]];
		for(int i=1;i<=m;++i) bag[i]+=bag[i-1];
		for(int i=n;i>=1;--i) sa[bag[rk[tp[i]]]--]=tp[i];
		p=1;
		for(int i=1;i<=n;++i) old[i]=rk[i];
		rk[sa[1]]=1;
		for(int i=2;i<=n;++i)
			if(old[sa[i]]==old[sa[i-1]] && old[sa[i]+w]==old[sa[i-1]+w])
				rk[sa[i]]=p;
			else rk[sa[i]]=++p;
		if(p==n) break;
	}
	memset(hi,0,sizeof hi);
	for(int i=1,k=0;i<=n;++i){
		if(k) --k;
		while(s[i+k]==s[sa[rk[i]-1]+k]) ++k;
		hi[rk[i]]=k;
	}
	for(int i=0;i<=19;++i){
		for(int j=1;j<=n;++j){
			rmq[j][i]=0;
		}
	}
	for(int i=1;i<=n;++i) rmq[i][0]=hi[i];
	for(int i=1;i<=19;++i){
		for(int j=1;j+(1<<i-1)<=n;++j){
			rmq[j][i]=min(rmq[j][i-1],rmq[j+(1<<i-1)][i-1]);
		}
	}
	return ;
}
struct node{
	int ls,rs;
}tree[20000005];
int ntot;
int tot,head[10000005],nxt[20000005],ver[20000005],len[20000005];
inline void add_edge(int x,int y,int z){
	++tot,nxt[tot]=head[x],head[x]=tot;
	ver[tot]=y,len[tot]=z;
	return ;
}
struct info{
	int l,r;
}A[200005],B[200005];
int na,nb,root[200005];
vector<int>Len[200005];
void ins(int now,int l,int r,int x,int v){
	if(l==r){
		add_edge(now,v,0);
		return ;
	}
	int mid=l+r>>1;
	if(x<=mid){
		head[ntot+1]=head[tree[now].ls];
		tree[ntot+1]=tree[tree[now].ls];
		tree[now].ls=++ntot;
		add_edge(now,tree[now].ls,0);
		ins(tree[now].ls,l,mid,x,v);
	}
	else {
		head[ntot+1]=head[tree[now].rs];
		tree[ntot+1]=tree[tree[now].rs];
		tree[now].rs=++ntot;
		add_edge(now,tree[now].rs,0);
		ins(tree[now].rs,mid+1,r,x,v);
	}
	return ;
}
void build(){
	memset(root,0,sizeof root);
	ntot=na;
	root[n+1]=++ntot;
	for(int i=n;i>=1;--i){
		int S=Len[i].size();
		root[i]=++ntot;
		tree[root[i]]=tree[root[i+1]];
		for(int j=0;j<S;++j){
			ins(root[i],1,n,rk[A[Len[i][j]].l],Len[i][j]);
		}
	}
	return ;
}
int xx,vv;
void link(int now,int l,int r,int L,int R){
	if(!now) return ;
	if(l==L && r==R){
		add_edge(xx,now,vv);
		return ;
	}
	int mid=l+r>>1;
	if(R<=mid) link(tree[now].ls,l,mid,L,R);
	else if(L>=mid+1) link(tree[now].rs,mid+1,r,L,R);
	else link(tree[now].ls,l,mid,L,mid),
		 link(tree[now].rs,mid+1,r,mid+1,R);
	return ; 
}
int flag=0,ed,rd[10000005];
long long dp[10000005];
queue<int>q;
void solve(){
	scanf("%s",s+1);ntot=tot=0;
	n=strlen(s+1);flag=0;
	for(int i=1;i<=n;++i) Len[i].clear();
	get_sa();
	scanf("%d",&na);
	for(int i=1;i<=na;++i) 
		A[i].l=read(),A[i].r=read(),
		Len[A[i].r-A[i].l+1].push_back(i);
	build();
	scanf("%d",&nb);
	for(int i=1;i<=nb;++i) B[i].l=read(),B[i].r=read();
	scanf("%d",&m);int x,y,l,r,mid,L,R,lim;
	for(int i=1;i<=m;++i){
		x=read(),y=read();
		lim=B[y].r-B[y].l+1;
		l=1,r=rk[B[y].l];
		while(l<r){
			mid=l+r>>1;
			if(lcp(mid,rk[B[y].l])>=lim) r=mid;
			else l=mid+1;
		}
		L=l;
		l=rk[B[y].l],r=n;
		while(l<r){
			mid=l+r+1>>1;
			if(lcp(rk[B[y].l],mid)>=lim) l=mid;
			else r=mid-1;
		}
		R=l;
		xx=x,vv=A[x].r-A[x].l+1;
		link(root[lim],1,n,L,R);
	}
	ed=++ntot;
	for(int i=1;i<=na;++i) add_edge(i,ed,A[i].r-A[i].l+1);
	for(int i=1;i<=ntot;++i) dp[i]=0ll,rd[i]=0;
	for(int i=1;i<=ntot;++i){
		for(int j=head[i];j;j=nxt[j]){
			++rd[ver[j]];
		}
	}
	for(int i=1;i<=ntot;++i)
		if(!rd[i]) q.push(i);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];i;i=nxt[i]){
			dp[ver[i]]=max(dp[ver[i]],dp[u]+1ll*len[i]);
			--rd[ver[i]];
			if(!rd[ver[i]]) q.push(ver[i]);
		}
	}
	for(int i=1;i<=ntot;++i) if(rd[i]) flag=1;
	if(!flag) printf("%lld\n",dp[ed]);else printf("-1\n");
	for(int i=1;i<=ntot;++i) tree[i].ls=tree[i].rs=0;
	for(int i=1;i<=ntot;++i) head[i]=0;
	return ;
}
2022/4/11 17:37
加载中...