解题思路:
题目后貌似还有一段提示:
但考试的时候完全看不懂它给的泰勒展开式,只打了可以暴力走和
x=1
的部分,就是LCT维护路径和。
考试后看了题解,原来它的意思就是取 x0=0 , f(x) 可以化成多项式形式,每项系数就是 fi(0)i!。n=11 精度就够了,然后Splay维护每一项系数的和,询问时每项乘以 xi 就行了。
对导数不熟悉的可看:http://blog.csdn.net/cdsszjj/article/details/74600569
有常见导数大概的简介。
再说一下每个函数的泰勒展开(取
x0=0
):
(1)sin(ax+b)=sin(b)+acos(b)1!x−a2sin(b)2!x2−a3cos(b)3!x3+a4sin(b)4!x4+……
(2)eax+b=eb+aeb1!x+a2eb2!x2+a3eb3!x3+……
(3)ax+b=ax+b
(要是只有这个我考试还是会做的……呵呵)
ps:c++库中有函数exp(b)可以直接得到 eb 的值,我考试时竟然二分去找了……
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=100005,lim=11;
int n,m;
int top,stk[N];
int tot,son[N][2],fa[N],rev[N];
double a[N][lim],sum[N][lim];
char s[20];
ll fac[lim];
inline void update(int x)
{
for(int i=0;i<lim;i++)
sum[x][i]=sum[son[x][0]][i]+sum[son[x][1]][i]+a[x][i];
}
inline int which(int x)
{
return son[fa[x]][1]==x;
}
inline bool rt(int x)
{
return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
inline void pushdown(int x)
{
swap(son[x][0],son[x][1]);
rev[x]=0;
if(son[x][0])rev[son[x][0]]^=1;
if(son[x][1])rev[son[x][1]]^=1;
}
inline void Rotate(int x)
{
int y=fa[x],z=fa[y],t=which(x);
if(!rt(y))son[z][which(y)]=x;
fa[y]=x,fa[x]=z;
son[y][t]=son[x][t^1],son[x][t^1]=y;
if(son[y][t])fa[son[y][t]]=y;
update(y),update(x);
}
inline void Splay(int x)
{
stk[top=1]=x;
for(int i=x;!rt(i);i=fa[i])stk[++top]=fa[i];
for(int i=top;i;i--)if(rev[stk[i]])pushdown(stk[i]);
while(!rt(x))
{
if(!rt(fa[x]))
which(x)==which(fa[x])?Rotate(fa[x]):Rotate(x);
Rotate(x);
}
}
inline void Access(int x)
{
for(int y=0;x;y=x,x=fa[x])
{
Splay(x),son[x][1]=y;
if(y)fa[y]=x;
update(x);
}
}
inline int Findroot(int x)
{
Access(x),Splay(x);
if(rev[x])pushdown(x);
while(son[x][0])
{
x=son[x][0];
if(rev[x])pushdown(x);
}
return x;
}
inline void Makeroot(int x)
{
Access(x),Splay(x);
rev[x]^=1;
}
inline void Link(int x,int y)
{
Makeroot(x),fa[x]=y;
}
inline void Cut(int x,int y)
{
Makeroot(x),Access(y),Splay(y);
fa[x]=son[y][0]=0;
}
inline double query(int u,int v,double x)
{
Makeroot(u),Access(v),Splay(v);
double tmp=1,res=0;
for(int i=0;i<lim;i++)
res+=tmp*sum[v][i],tmp*=x;
return res;
}
inline void trans(int op,double *a,double A,double B)
{
if(op==1)
{
double Sin=sin(B),Cos=cos(B),tmp=1;int f;
for(int i=0;i<lim;i++)
{
f=((i>>1)&1)?-1:1;
a[i]=f*tmp*(i&1?Cos:Sin)/fac[i];
tmp*=A;
}
}
else if(op==2)
{
double eb=exp(B),tmp=1;
for(int i=0;i<lim;i++)
{
a[i]=tmp*eb/fac[i];
tmp*=A;
}
}
else
{
a[0]=B,a[1]=A;
for(int i=2;i<lim;i++)a[i]=0;
}
}
int main()
{
//freopen("lx.in","r",stdin);
//freopen("lx.out","w",stdout);
fac[0]=1;
for(int i=1;i<lim;i++)fac[i]=1ll*fac[i-1]*i;
int op,u,v;double A,B,x;
n=getint(),m=getint();scanf("%s",s);
for(int i=1;i<=n;i++)
{
op=getint();scanf("%lf%lf",&A,&B);
trans(op,a[i],A,B);
}
while(m--)
{
scanf("%s",s);u=getint()+1,v=getint()+1;
if(s[0]=='a')Link(u,v);
else if(s[0]=='d')Cut(u,v);
else if(s[0]=='t')
{
scanf("%lf",&x);
if(Findroot(u)!=Findroot(v))puts("unreachable");
else printf("%.9f\n",query(u,v,x));
}
else
{
scanf("%lf%lf",&A,&B);
Makeroot(u);
trans(--v,a[u],A,B);
update(u);
}
}
}