e和sin信息不能直接合并
泰勒展开,大于21次太小,认为是0,保留前21次多项式即可
然后就把e,sin ,kx+b都变成多项式了,pushup合并
上LCT
// luogu-judger-enable-o2 // luogu-judger-enable-o2 #include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') #define ld double using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(' ');} namespace Miracle{ const int N=1e5+5; const int K=22; int n,m; struct Poly{ ld a[K]; Poly(){memset(a,0,sizeof a);} il ld &operator[](const int &x){return a[x];} il const ld &operator[](const int &x) const {return a[x];} Poly friend operator +(const Poly &a,const Poly &b){ Poly c; for(reg i=0;i<K;++i){ c.a[i]=a.a[i]+b.a[i]; } return c; } ld calc(ld x){ ld tmp=1,ret=0; for(reg i=0;i<K;++i){ ret=ret+a[i]*tmp; tmp=tmp*x; } return ret; } }; int C[30][30]; ld jie[K],ma[K],mb[K]; Poly exp(double a,double b){ Poly ret; ma[0]=1;mb[0]=1; for(reg i=1;i<K;++i){ ma[i]=ma[i-1]*a; mb[i]=mb[i-1]*b; } for(reg i=0;i<K;++i){ for(reg j=0;j<=i;++j){ ret.a[j]+=C[i][j]*ma[j]*mb[i-j]*jie[i]; } } return ret; } Poly sin(double a,double b){ Poly ret; ma[0]=1;mb[0]=1; for(reg i=1;i<K;++i){ ma[i]=ma[i-1]*a; mb[i]=mb[i-1]*b; } for(reg i=1;i<K;i+=2){ for(reg j=0;j<=i;++j){ if(((i-1)/2)&1){ ret.a[j]-=C[i][j]*ma[j]*mb[i-j]*jie[i]; }else{ ret.a[j]+=C[i][j]*ma[j]*mb[i-j]*jie[i]; } } } return ret; } Poly init(int typ,double a,double b){ if(typ==1) return sin(a,b); if(typ==2) return exp(a,b); Poly ret; ret.a[1]=a; ret.a[0]=b; return ret; } struct node{ int ch[2],fa; int rev; Poly f,sum; }t[N]; #define ls t[x].ch[0] #define rs t[x].ch[1] void pushup(int x){ if(!x) return; t[x].sum=t[ls].sum+t[rs].sum+t[x].f; } bool nrt(int x){ return t[t[x].fa].ch[0]==x||t[t[x].fa].ch[1]==x; } void rev(int x){ t[x].rev^=1; swap(ls,rs); } void pushdown(int x){ if(t[x].rev){ rev(ls);rev(rs); t[x].rev=0; } } void rotate(int x){ int y=t[x].fa,d=t[y].ch[1]==x; t[t[y].ch[d]=t[x].ch[!d]].fa=y; if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x; else t[x].fa=t[y].fa; t[t[x].ch[!d]=y].fa=x; pushup(y); } int sta[N]; void splay(int x){ int y=x,z=0; sta[++z]=x; while(nrt(y)) y=t[y].fa,sta[++z]=y; while(z) pushdown(sta[z--]); while(nrt(x)){ y=t[x].fa,z=t[y].fa; if(nrt(y)){ rotate((t[y].ch[0]==x)==(t[z].ch[0]==y)?y:x); } rotate(x); } pushup(x); } void access(int x){ for(reg y=0;x;y=x,x=t[x].fa){ splay(x);t[x].ch[1]=y;pushup(x); } } void makert(int x){ access(x);splay(x);rev(x); } void link(int x,int y){ makert(x);t[x].fa=y; } void split(int x,int y){ makert(x);access(y);splay(y); } void cut(int x,int y){ split(x,y); t[y].ch[0]=t[x].fa=0; pushup(y); } int findrt(int x){ access(x);splay(x); while(ls) x=ls; splay(x); return x; } ld query(int x,int y,ld v){ split(x,y); return t[y].sum.calc(v); } char s[233]; int main(){ char haha[233]; rd(n);rd(m);scanf("%s",haha+1); int typ; ld a,b; int x,y; C[0][0]=1; for(reg i=1;i<=K;++i){ C[i][0]=1; for(reg j=1;j<=K;++j){ C[i][j]=C[i-1][j]+C[i-1][j-1]; } } jie[0]=jie[1]=1; for(reg i=2;i<=K;++i){ jie[i]=jie[i-1]/i; } for(reg i=1;i<=n;++i){ rd(typ);scanf("%lf%lf",&a,&b); t[i].f=init(typ,a,b); pushup(i); } while(m--){ scanf("%s",s+1); if(s[1]=='a'){ rd(x);rd(y); ++x;++y; link(x,y); }else if(s[1]=='d'){ rd(x);rd(y); ++x;++y; cut(x,y); }else if(s[1]=='m'){ rd(x);rd(typ);scanf("%lf%lf",&a,&b); ++x; access(x);splay(x); t[x].f=init(typ,a,b); pushup(x); }else { // cout<<" tr "<<endl; rd(x);rd(y);scanf("%lf",&a); ++x;++y; // cout<<x<<" "<<y<<" a "<<a<<endl; if(findrt(x)==findrt(y)) printf("%.10lf ",query(x,y,a)); else puts("unreachable"); } } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/4/11 20:11:40 */
多项式可以支持合并