题解:
这是一道数学题。
看一眼会发现暴力跑链会超时。
所以我们需要一些神奇的东西。
泰勒展开:
最后那个东西可以当作无穷小。
所以我们可以提一下:
所以我们用LCT维护树链的$f(x0)$前k阶导数就好了。
还有,这道题卡精,一定要将单点值放在函数里面。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 100050 #define db double inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,m,f[N]; char typ[10]; db dv[16],a[N],b[N]; /* void F1(int x) { if(!x)return ; db A = 1.0; db sn = sin(b),cs = cos(b); for(int i=0;i<=15;i++,A*=a) { if(i%4==0)f[x][i] = A*sn; else if(i%4==1)f[x][i] = A*cs; else if(i%4==2)f[x][i] = -A*sn; else f[x][i] = -A*cs; } } void F2(int x) { if(!x)return ; db A = 1.0,ex = exp(b); for(int i=0;i<=15;i++,A*=a) f[x][i] = A*ex; } void F3(int x) { if(!x)return ; f[x][0] = b; f[x][1] = a; } */ struct LCT { int fa[N],ch[N][2]; db v[N][16]; bool res[N]; bool isroot(int x) { return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1]; } void update(int u) { for(int i=0;i<=15;i++) v[u][i] = v[ch[u][0]][i] + v[ch[u][1]][i]; if(f[u]==1) { db A = 1.0; db sn = sin(b[u]),cs = cos(b[u]); for(int i=0;i<=15;i++,A*=a[u]) { if(i%4==0)v[u][i] += A*sn; else if(i%4==1)v[u][i] += A*cs; else if(i%4==2)v[u][i] -= A*sn; else v[u][i] -= A*cs; } }else if(f[u]==2) { db A = 1.0,ex = exp(b[u]); for(int i=0;i<=15;i++,A*=a[u]) v[u][i] += A*ex; }else { v[u][0]+=b[u]; v[u][1]+=a[u]; } } void reser(int u) { res[u]^=1; swap(ch[u][0],ch[u][1]); } void pushdown(int u) { if(res[u]) { reser(ch[u][0]); reser(ch[u][1]); res[u] = 0; } } int st[N],tl; void down(int x) { st[tl=1]=x; while(!isroot(x))x=fa[x],st[++tl] = x; while(tl)pushdown(st[tl]),tl--; } void rotate(int x) { int y = fa[x],z = fa[y],k = (ch[y][1]==x); if(!isroot(y))ch[z][ch[z][1]==y] = x; fa[x] = z; ch[y][k] = ch[x][!k] , fa[ch[x][!k]] = y; ch[x][!k] = y,fa[y] = x; update(y),update(x); } void splay(int x) { down(x); while(!isroot(x)) { int y = fa[x],z = fa[y]; if(!isroot(y)) (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y); rotate(x); } } void access(int x) { int y = 0; while(x) { splay(x); ch[x][1] = y; update(x); y = x,x = fa[x]; } } void mtr(int x) { access(x); splay(x); reser(x); } void link(int x,int y) { mtr(x); fa[x] = y; } void cut(int x,int y) { mtr(x); access(y); splay(y); ch[y][0] = fa[x] = 0; update(y); } void Magic(int x) { splay(x); update(x); } int findrt(int x) { access(x); splay(x); while(ch[x][0])x=ch[x][0]; return x; } void query(db k,int x,int y) { mtr(x); access(y); splay(y); db ans = 0.0,D = k,A = 1.0; for(int i=0;i<=15;i++,A*=D) { ans += A*v[y][i]/dv[i]; } printf("%.8e ",ans); } }tr; int main() { n = rd(),m = rd(); scanf("%s",typ+1); dv[0]=1.0; for(int i=1;i<=15;i++) dv[i] = dv[i-1]*(db)i; for(int i=1;i<=n;i++) { f[i] = rd();scanf("%lf%lf",&a[i],&b[i]); } for(int x,y,i=1;i<=m;i++) { scanf("%s",typ+1); x = rd(),y = rd(); if(typ[1]=='a')tr.link(x+1,y+1); if(typ[1]=='d')tr.cut(x+1,y+1); if(typ[1]=='m') { f[x+1]=y; scanf("%lf%lf",&a[x+1],&b[x+1]); tr.Magic(x+1); } if(typ[1]=='t') { scanf("%lf",&a[0]); if(tr.findrt(x+1)!=tr.findrt(y+1)) { puts("unreachable"); }else tr.query(a[0],x+1,y+1); } } return 0; }