传送门:bzoj5020
题解
显然是在LCT上维护某些信息。
对于类型 3 : f ( x ) = a x + b 3:f(x)=ax+b 3:f(x)=ax+b只需维护路径上 a , b a,b a,b和。
考虑将 s i n ( a x + b ) , e a x + b sin(ax+b),e^{ax+b} sin(ax+b),eax+b泰勒展开转成多项式后维护前15项(保证精度)即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int N=1e5+10;
int n,m;
db fnv[15],ans;
char cp;
inline void rd(int &x)
{
cp=getchar();x=0;
for(;!isdigit(cp);cp=getchar());
for(;isdigit(cp);cp=getchar()) x=x*10+(cp^48);
}
inline void trs(db *s)
{
int i,tp;db a,b,nw=1.0,sn,cs;
rd(tp);scanf("%lf%lf",&a,&b);
if(tp==1){
sn=sin(b),cs=cos(b);
for(i=0;i<15;i+=4){
s[i]=nw*sn*fnv[i];nw*=a;
if(i+1<15) s[i+1]=nw*cs*fnv[i+1];nw*=a;
if(i+2<15) s[i+2]=-nw*sn*fnv[i+2];nw*=a;
if(i+3<15) s[i+3]=-nw*cs*fnv[i+3];nw*=a;
}
}else if(tp==2){
sn=exp(b);
for(i=0;i<15;++i,nw*=a) s[i]=sn*nw*fnv[i];
}else{
s[0]=b;s[1]=a;for(i=2;i<15;++i) s[i]=0;
}
}
namespace LCT{
#define F(x) t[x].fa
#define lc(x) t[x].ch[0]
#define rc(x) t[x].ch[1]
#define notrt(x) (F(x)&&((lc(F(x))==x)||(rc(F(x))==x)))
struct node{
int fa,ch[2];bool rv;
db xs[17],ss[17];
node(){rv=0;memset(ss,0,sizeof(ss));}
}t[N];
int stk[N],top;
inline void pu(int x){
int l=lc(x),r=rc(x),i;
for(i=0;i<15;++i) t[x].ss[i]=t[x].xs[i]+t[l].ss[i]+t[r].ss[i];
}
inline void dn(int x){
if(!t[x].rv) return;
swap(lc(x),rc(x));
if(lc(x)) t[lc(x)].rv^=1;
if(rc(x)) t[rc(x)].rv^=1;
t[x].rv=0;
}
inline void rot(int x){
int y=F(x),z=F(y),dr=(rc(y)==x);
t[y].ch[dr]=t[x].ch[dr^1];
if(t[y].ch[dr]) F(t[y].ch[dr])=y;
F(x)=z;if(notrt(y)) t[z].ch[(rc(z)==y)]=x;
F(y)=x;t[x].ch[dr^1]=y;pu(y);
}
inline void splay(int x)
{
int y=x,z;
for(;;y=F(y)) {stk[++top]=y;if(!notrt(y)) break;}
for(;top;--top) dn(stk[top]);
for(;notrt(x);rot(x)){
y=F(x);z=F(y);
if(notrt(y))
((rc(y)==x)^(rc(z)==y))?rot(x):rot(y);
}
pu(x);
}
inline void setrs(int x,int rs){splay(x);rc(x)=rs;pu(x);}
inline void access(int x){for(setrs(x,0);F(x);x=F(x)) setrs(F(x),x);}
inline void mkrt(int x){access(x);splay(x);t[x].rv^=1;}
inline int fdrt(int x){
access(x);splay(x);
for(;lc(x);x=lc(x));
return x;}
inline bool iscon(int x,int y){mkrt(x);return x==fdrt(y);}
inline void lk(int x,int y){mkrt(x);F(x)=y;}
inline void ct(int x,int y){setrs(x,0);setrs(y,0);F(x)==y?F(x)=0:F(y)=0;}
}
using namespace LCT;
int main(){
int i,j,x,y;db a,b;fnv[0]=1.0;
for(i=1;i<15;++i) fnv[i]=fnv[i-1]/(db)i;
rd(n);rd(m);rd(i);
for(i=1;i<=n;++i) trs(t[i].xs);
for(;m;--m){
for(cp=getchar();!isalpha(cp);cp=getchar());
if(cp=='a'){rd(x);rd(y);lk(x+1,y+1);}
else if(cp=='d'){rd(x);rd(y);ct(x+1,y+1);}
else if(cp=='m'){rd(x);x++;splay(x);trs(t[x].xs);pu(x);}
else{
rd(x);rd(y);x++;y++;scanf("%lf",&a);
if(!iscon(x,y)) puts("unreachable");
else{
ans=0;b=1;
mkrt(x);access(y);splay(y);
for(i=0;i<15;++i,b*=a) ans+=b*t[y].ss[i];
printf("%.9lf\n",ans);
}
}
}
return 0;
}