题解:
lct+解线性方程组
首先先把每一个环搞出来,然后再建立一个额外的点
然后解方程。。
代码:
#include <bits/stdc++.h> using namespace std; const int N=300005,M=10007; int n,Q,tim,fa[N],dir[N],x,k,p,b,vis[N],ch[N][2],ni[N]; char s[4]; int which(int x){return ch[fa[x]][1]==x;} struct node { int k,b; node(){} node(int k,int b):k(k),b(b){} friend node operator + (const node &r1,const node &r2) {return node(r1.k*r2.k%M,(r2.k*r1.b%M+r2.b)%M);} }a[N],sum[N]; void dfs(int x) { if (vis[x])return; vis[x]=tim; if (vis[fa[x]]==tim) { dir[x]=fa[x]; fa[x]=0; } else dfs(fa[x]); } int isroot(int x){return !fa[x]||ch[fa[x]][which(x)]!=x;} void pushup(int x) { sum[x]=a[x]; if (ch[x][0])sum[x]=sum[ch[x][0]]+a[x]; if (ch[x][1])sum[x]=sum[x]+sum[ch[x][1]]; } void rotate(int x) { int y=fa[x],k=which(x); ch[y][k]=ch[x][k^1]; ch[x][k^1]=y; if (!isroot(y))ch[fa[y]][which(y)]=x; fa[x]=fa[y];fa[y]=x; fa[ch[y][k]]=y; pushup(y);pushup(x); } void splay(int x) { for (int y=fa[x];!isroot(x);rotate(x),y=fa[x]) if (!isroot(y))rotate((ch[y][0]==x)==(ch[fa[y]][0]==y)?y:x); } void access(int x) { int t=0; while(x) { splay(x); ch[x][1]=t; pushup(x); t=x;x=fa[x]; } } int findroot(int x) { access(x);splay(x); while(ch[x][0])x=ch[x][0]; splay(x); return x; } int inc(int x,int y) { access(dir[y]);splay(dir[y]); splay(x); return x==dir[y]||!isroot(dir[y]); } void cut(int x){access(x);splay(x);ch[x][0]=fa[ch[x][0]]=0;pushup(x);} int main() { ni[1]=1; for (int i=2;i<M;i++)ni[i]=(M-M/i)*ni[M%i]%M; scanf("%d",&n); for (int i=1;i<=n;i++)scanf("%d%d%d",&a[i].k,&fa[i],&a[i].b); for (int i=1;i<=n;i++) if (!vis[i])tim++,dfs(i); scanf("%d",&Q); while (Q--) { scanf("%s",s+1); if (s[1]==‘A‘) { scanf("%d",&x); access(x);splay(x); node t1=sum[x]; int t=findroot(x); access(dir[t]);splay(dir[t]); node t2=sum[dir[t]]; if (t2.k==1) { if (t2.b)puts("-1"); else puts("-2"); continue; } int v1=ni[(1-t2.k+M)%M]*t2.b%M; printf("%d\n",(t1.k*v1%M+t1.b)%M); } else { scanf("%d%d%d%d",&x,&k,&p,&b); access(x);splay(x); a[x]=node(k,b);pushup(x); int t=findroot(x); if (t==x) { if (findroot(p)==t)dir[t]=p; else dir[t]=0,fa[t]=p; } else { if (inc(x,t)) { cut(x); access(t);splay(t); fa[t]=dir[t];dir[t]=0; if (findroot(p)==x)dir[x]=p; else fa[x]=p; } else { cut(x); if (findroot(p)==x)dir[x]=p; else fa[x]=p; } } } } return 0; }