其他分享
首页 > 其他分享> > 21.10.10模拟 魔方俱乐部

21.10.10模拟 魔方俱乐部

作者:互联网

fateice来到了膜方俱乐部旅行。膜方俱乐部有N个分部,每个分部均有且仅有一个虫洞,但是这虫洞只能通往一个分部。每个分部有一个orzFang价值,第 i 个分部的orzFang价值为A[i]。
现在他想知道,从i个分部出发,并只通过虫洞前往下一个分部,orzFang价值之和最多是多少(到达一个分部多次只计算 1 次orzFang价值)。

做了好几次了,每次都是写递归80tps。。这次补下100分的循环写法。


const int N = 2e5 + 79;
int a[N], to[N];
int n;
int v[N], in[N], ans[N],q[N];
int main() {
	freopen("travel.in","r",stdin);
	freopen("travel.out","w",stdout);
	read(n);
	rep(i, 1, n) {
		read(a[i]);
	}
	rep(i, 1, n) {
		read(to[i]);
		++in[to[i]];
	}
	rep(i,1,n){
		if(!in[i]) q[++q[0]]=i;
	}
	rep(kkk,1,q[0]){
		int x=q[kkk];
		v[x]=1;
		if(!--in[to[x]]) q[++q[0]]=to[x];
	}
	
	rep(i,1,n){
		if(!v[i]){
			int st(i),sum(a[i]);
			int x(i);
			v[x]=1;
			while(to[x]!=st){
				x=to[x];
				v[x]=1;
				sum+=a[x];
			}
			x=i;
			ans[x]=sum;
			while(to[x]!=st){
				x=to[x];
				ans[x]=sum;
			}
		}
	}
	drp(i,q[0],1){
		ans[q[i]]=a[q[i]]+ans[to[q[i]]];
	}
	rep(i, 1, n) out(ans[i], '\n');
	return 0;
}

MLE


const int N = 2e5 + 79;
int a[N], to[N];
int n;
int vis[N], in[N], ans[N];
inline void dfs(int x) {
	vis[x] = 1;
	if(!(--in[to[x]]))dfs(to[x]);
}


inline int calccircle(int x, int tot) {
	ans[x] = tot;
	if(ans[to[x]]) return tot;
	else return ans[x] = calccircle(to[x], tot + a[to[x]]);
}
inline int calc(int x) {
	if(ans[x]) return ans[x];
	else return ans[x] = calc(to[x]) +a[x];
}
int main() {
	freopen("travel.in","r",stdin);
	freopen("travel.out","w",stdout);
	read(n);
	rep(i, 1, n) {
		read(a[i]);
	}
	rep(i, 1, n) {
		read(to[i]);
		++in[to[i]];
	}
	rep(i, 1, n) {
		if(!in[i] && !vis[i]) dfs(i);
	}
	rep(i, 1, n) {
		if(in[i] && !ans[i]) calccircle(i, a[i]);
	}
	rep(i, 1, n) {
		if(!in[i] && !ans[i]) calc(i);
	}
	rep(i, 1, n) out(ans[i], '\n');
	return 0;
}

标签:10,return,魔方,int,rep,read,21.10,ans,分部
来源: https://www.cnblogs.com/QQ2519/p/15392160.html