bzoj2759 -- LCT

9 篇文章 0 订阅
神题
题解
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 30010
#define M 10007
struct Node{
    int k,b;
    Node(int k=0,int b=0):k(k),b(b){}
    Node operator + (Node a){
        return Node(k*a.k%M,(a.k*b+a.b)%M);
    }
}a[N],c[N];
int f[N],sf[N],ch[N][2];
int i,j,k,n,m,p,v[N],Q,x,y,z;
bool b[N];
char s[3];
inline void Dfs(int x){
    v[x]=i;
    if(!v[f[x]])Dfs(f[x]);else
    if(v[f[x]]==i)sf[x]=f[x],f[x]=0;
}
inline bool Get(int x){
    return ch[f[x]][1]==x;
}
inline void Up(int x){
    c[x]=c[ch[x][0]]+a[x]+c[ch[x][1]];
}
inline void Rotate(int x){
    int y=f[x];bool d=Get(x);
    if(b[y])b[x]=1,b[y]=0;else ch[f[y]][Get(y)]=x;
    ch[y][d]=ch[x][d^1];f[ch[y][d]]=y;
    f[x]=f[y];f[y]=x;ch[x][d^1]=y;Up(y);
}
inline void Splay(int x){
    for(;!b[x];Rotate(x))
    if(!b[f[x]])Rotate(Get(x)==Get(f[x])?f[x]:x);
    Up(x);
}
inline void Access(int x){
    int y=0;
    while(x){
        Splay(x);
        b[ch[x][1]]=1;ch[x][1]=y;b[y]=0;
        Up(y=x);x=f[x];
    }
}
inline void mr(int x){
    Access(x);Splay(x);
}
inline int Find(int x){
    mr(x);
    int t=x;
    for(;ch[t][0];t=ch[t][0]);
    return t;
}
inline void Ex_Gcd(int a,int b,int& x,int& y){
    if(!b){x=1;y=0;return;}
    Ex_Gcd(b,a%b,y,x);
    y-=a/b*x;
}
inline int Query(int x){
    int t=sf[Find(x)];
    mr(t);
    if(c[t].k==1){
        if(!c[t].b)return -2;
        return -1;
    }
    Ex_Gcd((c[t].k-1+M)%M,M,y,z);
    y=(y*(M-c[t].b)%M+M)%M;
    mr(x);
    return (y*c[x].k+c[x].b)%M;
}
inline void Update(int x,int y,Node z){
    int r=Find(x);
    a[x]=z;Up(x);
    if(x==r)sf[x]=0;else{
        mr(x);
        f[ch[x][0]]=0;b[ch[x][0]]=1;ch[x][0]=0;
        Up(x);
        if(Find(sf[r])!=r)mr(r),f[r]=sf[r],sf[r]=0;
    }
    mr(x);
    if(Find(y)==x)sf[x]=y;else f[x]=y;
}
int main(){
    scanf("%d",&n);c[0].k=1;
    for(i=1;i<=n;i++)scanf("%d%d%d",&a[i].k,&f[i],&a[i].b),b[i]=1,c[i]=a[i];
    for(i=1;i<=n;i++)if(!v[i])Dfs(i);
    scanf("%d",&Q);
    while(Q--){
        scanf("%s%d",s,&x);
        if(s[0]=='A')printf("%d\n",Query(x));else
        scanf("%d%d%d",&y,&k,&z),Update(x,k,Node(y,z));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值