[BZOJ 2759] 一个动态树好题
这题确实很好.
题解方面,网上有许多不错的题解,所以就不说了.
这题很需要注意细节.
#include<cstdio> using namespace std; #define ll long long #define up(i,j,n) for(int i=j;i<=n;i++) #define db long double #define pii pair<int,int> #define pb push_back #define FILE "dealing" template<class T> inline bool cmin(T& a,T b){return a>b?a=b,true:false;} template<class T> inline bool cmax(T& a,T b){return a<b?a=b,true:false;} template<class T> inline T squ(T a){return a*a;} const int maxn=210000+10,mod=10007,base=23; int read(){ int x=0,f=1,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); return x*f; } struct Node{ int y,next,v; }e[maxn];int len,linkk[maxn]; void insert(int x,int y,int v){ e[++len].y=y; e[len].next=linkk[x]; linkk[x]=len; e[len].v=v; } int n,m; int fa[maxn],sf[maxn],c[maxn][2]; bool isroot(int x){ return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; } struct node{ int k,b; node(int k=1,int b=0):k(k),b(b){} }li[maxn],sum[maxn]; node operator+(const node& a,const node& b){ node c; c.k=a.k*b.k%mod; c.b=(a.b*b.k%mod+b.b)%mod; return c; } void updata(int x){ sum[x]=sum[c[x][0]]+li[x]+sum[c[x][1]]; } void rotate(int x){ int y=fa[x],z=fa[y],d=c[y][1]==x; if(!isroot(y))c[z][c[z][1]==y]=x; fa[y]=x;fa[x]=z;if(c[x][d^1])fa[c[x][d^1]]=y; c[y][d]=c[x][d^1],c[x][d^1]=y; updata(y);updata(x); } void splay(int x){ if(!x)return; while(!isroot(x)){ int y=fa[x],z=fa[y]; if(!isroot(y)){ if(c[y][1]==x^c[z][1]==y)rotate(x); else rotate(y); } rotate(x); } } void access(int x){ for(int t=0;x;t=x,x=fa[x]){ splay(x); c[x][1]=t; updata(x); } } int root,vis[maxn]; void dfs(int x,int fa){ vis[x]=1; for(int i=linkk[x];i;i=e[i].next){ if(e[i].y==fa)continue; if(!vis[e[i].y])dfs(e[i].y,x); else root=x; } } int inv[maxn]; int getroot(int x){ access(x);splay(x); while(c[x][0])x=c[x][0]; return x; } int getl(int x){ access(x);splay(x); x=c[x][0];while(c[x][1])x=c[x][1]; return x; } int tk[maxn]; int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); n=read(); up(i,1,n){ li[i].k=read(); fa[i]=read(); li[i].b=read(); sum[i]=li[i]; insert(i,fa[i],1); insert(fa[i],i,-1); tk[i]=fa[i]; } up(i,1,n){ if(vis[i])continue; root=0; dfs(i,0); sf[root]=fa[root]; fa[root]=0; } m=read(); inv[0]=inv[1]=1; for(int i=2;i<mod;i++)inv[i]=(mod-(mod/i)*inv[mod%i]%mod)%mod; up(i,1,m){ char s; scanf(" %c",&s); if(s=='A'){ int x=read(); int root=getroot(x),y=sf[root]; access(y);splay(y); node b=sum[y]; if(b.k==1){ if(b.b==0)printf("%d\n",-2); else printf("-1\n"); } else { int key=(mod-b.b)%mod*inv[(b.k-1+mod)%mod]%mod; access(x);splay(x); printf("%d\n",(sum[x].k*key%mod+sum[x].b)%mod); } } else { int x=read(),k=read(),p=read(),b=read(); int ro=getroot(x); li[x]=node(k,b); updata(x); if(tk[x]==p)continue; tk[x]=p; if(ro==x){ sf[ro]=0; int ro2=getroot(p); if(ro2==ro)sf[ro]=p; else { access(ro);splay(ro); fa[ro]=p; } } else { int w=getl(x); access(x);splay(w); c[w][1]=fa[x]=0;updata(w); int y=sf[ro]; int ro2=getroot(y); if(ro2!=ro){ access(ro); splay(ro); fa[ro]=y; sf[ro]=0; } int ro3=getroot(p); access(x); splay(x); if(ro3!=x)fa[x]=p; else sf[x]=p; } } } return 0; }