【BZOJ2759】—一个动态树好题(LCT+Exgcd)
考虑说把向连边
那么显然最后会整个图形成一个基环森林
考虑对于一个环
任选一条边断开
将设为根,并且记录一个
对于每次询问,我们先找到的根
就可以用解出的值
然后
带入就可以得到了
修改的时候要判一下的位置
如果在之间就不用管
否则就把和连起来
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
const int mod=10007;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
struct node{
int k,b;
node(int _k=1,int _b=0):k(_k),b(_b){}
friend inline node operator +(cs node &a,cs node &b){
return node(a.k*b.k%mod,(a.b*b.k+b.b)%mod);
}
};
cs int N=300005;
inline void exgcd(int &x,int &y,int a,int b){
if(b==0){x=1,y=0;return;}
exgcd(y,x,b,a%b),y-=(a/b)*x;
}
inline int inv(int a){
int x,y;
exgcd(x,y,(a+mod)%mod,mod);
return (x+mod)%mod;
}
namespace Lct{
int fa[N],son[N][2],sf[N],rev[N];
node val[N],s[N];
#define lc(u) son[u][0]
#define rc(u) son[u][1]
inline void initnode(int u,int k,int b){
s[u]=val[u]=node(k,b);
}
inline bool isrc(int u){
return rc(fa[u])==u;
}
inline bool isrt(int u){
return lc(fa[u])!=u&&rc(fa[u])!=u;
}
inline void pushup(int u){
s[u]=s[lc(u)]+val[u]+s[rc(u)];
}
inline void pushdown(int u){
if(!rev[u])return;
if(lc(u))rev[lc(u)]^=1;
if(rc(u))rev[rc(u)]^=1;
swap(lc(u),rc(u));
rev[u]=0;
}
inline void rotate(int v){
int u=fa[v],z=fa[u];
int t=isrc(v);
fa[v]=z;
if(!isrt(u))son[z][isrc(u)]=v;
son[u][t]=son[v][t^1];
fa[son[v][t^1]]=u;
fa[u]=v,son[v][t^1]=u;
pushup(u),pushup(v);
}
int stk[N],top;
inline void splay(int u){
stk[top=1]=u;
for(int v=u;!isrt(v);v=fa[v])stk[++top]=fa[v];
for(int i=top;i;i--)pushdown(stk[i]);
while(!isrt(u)){
if(!isrt(fa[u]))
isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
rotate(u);
}
}
inline void access(int u){
for(int v=0;u;v=u,u=fa[u]){
splay(u),rc(u)=v;
if(v)fa[v]=u;
pushup(u);
}
}
inline void makert(int u){
access(u),splay(u),rev[u]^=1;
}
inline void link(int u,int v){
makert(u),splay(v),fa[u]=v;
}
inline void cut(int u,int v){
makert(u),access(v),splay(v);
fa[u]=lc(v)=0,pushup(v);
}
inline void split(int u,int v){
makert(u),access(v),splay(v);
}
inline int findrt(int u){
access(u),splay(u);
while(pushdown(u),lc(u))u=lc(u);
splay(u);return u;
}
inline int query(int u){
int pp=findrt(u);
access(sf[pp]),splay(sf[pp]);
int k=s[sf[pp]].k,b=s[sf[pp]].b;
if(k==1&&b)return -1;
if(k==1&&!b)return -2;
int v=(mod-b)*inv(k-1)%mod;
access(u),splay(u);
return (s[u].k*v+s[u].b)%mod;
}
inline void update(int u,int k,int p,int b){
access(u),splay(u),val[u]=node(k,b);
pushup(u);
int rt=findrt(u);
if(rt==u){sf[u]=0;}
else{
access(u),splay(u);
fa[lc(u)]=0,lc(u)=0;
pushup(u);
if(findrt(sf[rt])!=rt){
link(rt,sf[rt]),sf[rt]=0;
}
}
if(findrt(p)==u)sf[u]=p;
else link(u,p);
}
}
int n,m,p[N],vis[N],tot;
void dfs(int u){
vis[u]=tot;
if(vis[p[u]]!=tot){Lct::fa[u]=p[u];if(!vis[p[u]])dfs(p[u]);}
else Lct::sf[u]=p[u];
}
char op[5];
signed main(){
n=read();
for(int i=1;i<=n;i++){
int k=read();p[i]=read();int b=read();
Lct::initnode(i,k,b);
}
for(int i=1;i<=n;i++)if(!vis[i])++tot,dfs(i);
m=read();
while(m--){
scanf("%s",op+1);
if(op[1]=='A'){
int x=read();
cout<<Lct::query(x)<<'\n';
}
else{
int x=read(),k=read(),pp=read(),b=read();
Lct::update(x,k,pp,b);
}
}
}