关于刚才 AT 的 G
  • 板块学术版
  • 楼主PurslaneM2GA
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/7/15 21:44
  • 上次更新2023/11/3 09:37:52
查看原帖
关于刚才 AT 的 G
120947
PurslaneM2GA楼主2023/7/15 21:44

思路 : 就是建出基环树 , 然后树上差分 , 再处理环上无限循环 .

为啥会 Wa ( 样例都过不去 ) :

/*
这个显然构成了一棵基环树
每个节点分开贡献 
*/
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=2e5+10,MOD=998244353;
int n,k,to[MAXN],v[MAXN],vis[MAXN],ans[MAXN],flg[MAXN],cir[MAXN];
int fa[MAXN][21],dis[MAXN],anc[MAXN],pre[MAXN];
vector<int> g[MAXN]; 
vector<int> cirans[MAXN];
int qpow(int base,int p) {
	int ans=1;
	while(p) {
		if(p&1) ans=ans*base%MOD;
		base=base*base%MOD,p>>=1;	
	}
	return ans;
}
int revid[MAXN],pos[MAXN],len[MAXN]; //记录每个点所在环 , 在环上的位置 , 环的长度 
void solve(int u) {
	if(vis[u]) return ;
	vis[u]=1; if(cir[u]) return dis[u]=0,anc[u]=u,void();
	solve(to[u]),fa[u][0]=to[u];
	ffor(i,1,19) fa[u][i]=fa[fa[u][i-1]][i-1];	
	dis[u]=dis[to[u]]+1,anc[u]=anc[to[u]];
	return ;
}
void add(int cirid,int startpos,int v,int Len) {
	int reg=Len/len[cirid];
	cirans[cirid][1]=(cirans[cirid][1]+reg%MOD*v%MOD)%MOD;
	int rst=Len-reg*len[cirid]; if(rst==0) return ;
	if(len[cirid]-startpos+1>=rst) {
		cirans[cirid][startpos]=(cirans[cirid][startpos]+v)%MOD;
		cirans[cirid][startpos+rst]=(cirans[cirid][startpos+rst]-v)%MOD;
	}
	else {
		cirans[cirid][startpos]=(cirans[cirid][startpos]+v)%MOD;
		int nxt=rst-len[cirid]+startpos-1;
		cirans[cirid][1]=(cirans[cirid][1]+v)%MOD;
		cirans[cirid][nxt+1]=(cirans[cirid][nxt+1]-v)%MOD;
	}
	return ;
}
void dfs(int u) {
	for(auto v:g[u]) {
		dfs(v);	
		pre[u]=(pre[v]+pre[u])%MOD;
	}
	return ;
}
signed main() {
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n>>k;
	ffor(i,1,n) cin>>to[i];
	ffor(i,1,n) cin>>v[i];
	ffor(i,1,n) if(!flg[i]) {
		int u=i;
		while(!flg[u]) flg[u]=1,u=to[u];
		while(!cir[u]) cir[u]=1,u=to[u];
	}
	ffor(i,1,n) if(!cir[i]) g[to[i]].push_back(i);
	ffor(i,1,n) if(!vis[i]) solve(i);
	memset(vis,0,sizeof(vis)); 
	int cirsum=0;
	ffor(i,1,n) if(cir[i]&&!vis[i]) {
		++cirsum;
		cirans[cirsum].push_back(0);
		int u=i,tmp=0;
		while(!vis[u]) vis[u]=1,revid[u]=cirsum,pos[u]=++tmp,u=to[u],cirans[cirsum].push_back(0);
		cirans[cirsum].push_back(0),len[cirsum]=tmp;
	}
	ffor(i,1,n) {
		if(dis[i]>=k) {
			int u=i;
			roff(j,19,0) if(k&(1<<j)) u=fa[u][j];
			pre[fa[u][0]]=(pre[fa[u][0]]-v[i])%MOD,pre[fa[i][0]]=(pre[fa[i][0]]+v[i])%MOD;
		}
		else {
			int u=i;
			pre[fa[i][0]]=(pre[fa[i][0]]+v[i])%MOD;	
			u=to[anc[i]],add(revid[u],pos[u],v[i],k-dis[i]);
		}
	}
	ffor(i,1,cirsum) ffor(j,1,len[i]) cirans[i][j]=(cirans[i][j]+cirans[i][j-1])%MOD;
	k%=MOD;
	k=qpow(k,MOD-2);
	ffor(i,1,n) if(cir[i]) dfs(i);
	ffor(i,1,n) {
		int ans=pre[i];
		if(cir[i]) ans=ans+cirans[revid[i]][pos[i]];
		ans%=MOD,ans+=MOD,ans%=MOD;
		ans*=k,ans%=MOD;
		cout<<ans<<' ';
	}
	return 0;
}

调出来我给你几个关注 !

2023/7/15 21:44
加载中...