终于找到一个可以交的地方了…
考场上只写了LCT的60分暴力,因为那时候并看不懂什么泰勒展开…
前段时间学了微积分,学了泰勒展开,大概知道了是怎么回事
其实题目说的很清楚了…但是那时候就是看不懂,也不会求导什么的。
讲 sin(ax+b) , eax+b 和 ax+b 在x=0处展开可以得到:
sin(ax+b)=sin(b)+acos(b)x1!−a2sin(b)x22!−a3cos(b)x33!+a4sin(b)x44!+⋯
eax+b=eb+aebx1!+a2ebx22!+a3ebx33!+a4ebx44!+a5ebx55!+⋯
ax+b=ax+b
展开个14层左右,再用LCT来维护森林,每个节点多项式合并一下就可以了
果然我的LCT模板贼慢……
UPD:改了下代码,把func的结构去掉了,原来的取址常数大的一匹……顺便把展开的层数减小了一点
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=100010;
int n,m,typ;
double a,b;
char opt[20];
inline void add(double *a,double *b){
}
struct node{
node *ch[2],*fa;
int rev;
double F[25],T[25];
double val(const double &x){
double ret=T[0],gx=x;
long long fac=1;
for(int i=1;i<=10;i++)
ret+=T[i]*gx/fac,gx*=x,fac*=i+1;
return ret;
}
void Up(){
for(int i=0;i<=10;i++) T[i]=F[i];
if(ch[0]){
double *C=ch[0]->T;
for(int i=0;i<=10;i++)
T[i]+=C[i];
}
if(ch[1]){
double *C=ch[1]->T;
for(int i=0;i<=10;i++)
T[i]+=C[i];
}
}
void Push(){
if(!rev) return ;
swap(ch[0],ch[1]);
if(ch[0]) ch[0]->rev^=1;
if(ch[1]) ch[1]->rev^=1;
rev=0;
}
}c[N],*st[N];
int top;
inline bool isl(node *x){ return (!x->fa)||(x->fa->ch[0]!=x&&x->fa->ch[1]!=x); }
inline bool iss(node *x){ return x->fa&&x->fa->ch[1]==x; }
void Pushtop(node *x){
if(!isl(x)) Pushtop(x->fa);
x->Push();
}
void rot(node *x){
node *y=x->fa,*z=y->fa; int w=iss(x);
if(!isl(y)) z->ch[iss(y)]=x; x->fa=z;
if(y->ch[w]=x->ch[w^1]) y->ch[w]->fa=y;
x->ch[w^1]=y; y->fa=x; y->Up(); x->Up();
}
inline void splay(node *x){
Pushtop(x);
for(;!isl(x);rot(x))
if(!isl(x->fa))rot(iss(x)^iss(x->fa)?x:x->fa);
}
inline void access(node *x){
node *t=0;
for(;x;x=x->fa)
splay(x),x->ch[1]=t,t=x,x->Up();
}
inline void reverse(node *x){
access(x); splay(x); x->rev^=1;
}
inline void link(node *x,node *y){
reverse(x); x->fa=y; access(x); splay(x);
}
inline void cut(node *x,node *y){
reverse(x); access(y); splay(y); y->ch[0]=x->fa=0; y->Up();
}
inline bool linked(node *x,node *y){
reverse(x); access(y); splay(y);
while(y->ch[0]) y=y->ch[0];
return x==y;
}
double g[4];
inline void set(const int &u,const int &typ,const double &a,const double &b){
if(typ==1){
c[u].F[0]=sin(b);
double ga=a;
g[0]=sin(b); g[1]=cos(b); g[2]=-sin(b); g[3]=-cos(b); double *C=c[u].F;
for(int i=1;i<=10;i++)
C[i]=g[i%4]*ga,ga*=a;
}
else if(typ==2){
double eb=exp(b),ga=a,*C=c[u].F;
C[0]=eb;
for(int i=1;i<=10;i++)
C[i]=eb*ga,ga*=a;
}
else{
double *C=c[u].F;
C[0]=b,C[1]=a;
for(int i=2;i<=10;i++) C[i]=0;
}
}
inline void change(const int &u,const int &typ,const double &a,const double &b){
access(c+u); splay(c+u);
set(u,typ,a,b); c[u].Up();
}
inline void Query(const int &u,const int &v,const double &x){
if(!linked(c+u,c+v)) return (void)puts("unreachable");
reverse(c+u); access(c+v);
splay(c+v);
printf("%.8e\n",c[v].val(x));
}
int u,v;
double x;
int main(){
scanf("%d%d",&n,&m); scanf("%s",opt);
for(int i=1;i<=n;i++){
scanf("%d%lf%lf",&typ,&a,&b);
set(i,typ,a,b);
}
while(m--){
scanf("%s",opt);
if(opt[0]=='a')
scanf("%d%d",&u,&v),link(c+u+1,c+v+1);
else if(opt[0]=='d')
scanf("%d%d",&u,&v),cut(c+u+1,c+v+1);
else if(opt[0]=='m')
scanf("%d%d%lf%lf",&u,&typ,&a,&b),change(u+1,typ,a,b);
else
scanf("%d%d%lf",&u,&v,&x),Query(u+1,v+1,x);
}
return 0;
}