bzoj 5020(洛谷4546) [THUWC 2017]在美妙的数学王国中畅游——LCT+泰勒展开
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5020
https://www.luogu.org/problemnew/show/P4546
如果保证 x=1 ,则可以用 LCT 维护每个点的函数值。不然的话就用 LCT 拿出那条链,dfs 一下 splay 现算。可以得 60 分。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define db double using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } const int N=1e5+5; int n,m,fa[N],c[N][2],sta[N],top; db sm[N],vl[N]; bool fx,rev[N]; struct Node{ int f;db a,b; db cal(db x) { if(f==1)return sin(a*x+b); if(f==2)return exp(a*x+b); if(f==3)return a*x+b; } }a[N]; bool isroot(int cr){return c[fa[cr]][0]!=cr&&c[fa[cr]][1]!=cr;} void pshp(int cr){sm[cr]=sm[c[cr][0]]+sm[c[cr][1]]+vl[cr];} void Rev(int cr){if(rev[cr]){rev[cr]=0;rev[c[cr][0]]^=1;rev[c[cr][1]]^=1;swap(c[cr][0],c[cr][1]);}} void rotate(int x) { int y=fa[x],z=fa[y],d=(x==c[y][1]); if(!isroot(y))c[z][y==c[z][1]]=x;//!isroot(y) not !isroot(z) !! fa[x]=z; fa[y]=x; fa[c[x][!d]]=y; c[y][d]=c[x][!d]; c[x][!d]=y; if(fx)pshp(y),pshp(x); } void splay(int x) { sta[top=1]=x; for(int cr=x;!isroot(cr);cr=fa[cr])sta[++top]=fa[cr]; for(int i=top;i;i--)Rev(sta[i]); int y,z; while(!isroot(x)) { y=fa[x];z=fa[y]; if(!isroot(y)) ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y); rotate(x); } } void access(int cr) { for(int t=0;cr;splay(cr),c[cr][1]=t,pshp(cr),t=cr,cr=fa[cr]);//pshp()!! } void mkrt(int cr) { access(cr);splay(cr);rev[cr]^=1; } void link(int x,int y) { mkrt(x);fa[x]=y; } void cut(int x,int y) { mkrt(x);access(y);splay(y); fa[x]=c[y][0]=0;if(fx)sm[y]-=vl[x]; } void mdfy(int cr,int f,db a1,db b1) { if(fx)splay(cr),sm[cr]-=vl[cr]; a[cr].f=f;a[cr].a=a1;a[cr].b=b1; if(fx)vl[cr]=a[cr].cal(1),sm[cr]+=vl[cr]; } int fnd(int cr)//root of real tree { while(!isroot(cr))cr=fa[cr];return cr; } db dfs(int cr,db x) { db ret=a[cr].cal(x); if(c[cr][0])ret+=dfs(c[cr][0],x); if(c[cr][1])ret+=dfs(c[cr][1],x); return ret; } void print(db x) { bool fx=0;int t=0; if(x<1){fx=1;while(x<1)x*=10,t++;} if(x>=10){while(x>=10)x/=10,t++;} printf("%.8fe%c%03d\n",x,fx?'-':'+',t); } int main() { n=rdn();m=rdn();char ch[15];scanf("%s",ch); if(ch[1]=='0')fx=1; for(int i=1;i<=n;i++) { a[i].f=rdn();scanf("%lf%lf",&a[i].a,&a[i].b); if(fx)vl[i]=sm[i]=a[i].cal(1); } int u,v;db a,b,x; while(m--) { scanf("%s",ch); if(ch[0]=='a'){u=rdn()+1;v=rdn()+1;link(u,v);} if(ch[0]=='d'){u=rdn()+1;v=rdn()+1;cut(u,v);} if(ch[0]=='m'){u=rdn()+1;v=rdn();scanf("%lf%lf",&a,&b);mdfy(u,v,a,b);} if(ch[0]=='t') { u=rdn()+1;v=rdn()+1;scanf("%lf",&x); mkrt(u);access(v);splay(v); if(fnd(u)!=v)puts("unreachable"); else print(fx?sm[v]:dfs(v,x)); } } return 0; }
关于本题的求导和泰勒展开可以看这个:https://www.cnblogs.com/zhoushuyu/p/8148732.html
似乎还可以麦克劳林展开:https://www.cnblogs.com/Troywar/p/8982707.html
似乎展开成 12 项的多项式就差不多了,然后可以用 LCT 维护 12 项的系数和,算的时候乘上 xk 再除以阶乘就行。
那个 x0 好像取 0 就行了。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define db double #define ls c[cr][0] #define rs c[cr][1] int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } using namespace std; const int N=1e5+5,M=12; int n,fa[N],c[N][2],sta[N],top; bool rev[N]; db sm[N][M+5],vl[N][M+5],jc[N]; struct Node{ int f;db a,b; Node(int f=0,db a=0,db b=0):f(f),a(a),b(b) {} void cz(int cr) { if(f==1) { db p[5],lja=1; p[0]=sin(b);p[1]=cos(b);p[2]=-p[0];p[3]=-p[1]; for(int i=0;i<M;i+=4) for(int j=0;j<4;j++,lja*=a)sm[cr][i+j]=vl[cr][i+j]=p[j]*lja; } if(f==2) { db ml=exp(b),lja=1; for(int i=0;i<M;i++,lja*=a)sm[cr][i]=vl[cr][i]=ml*lja; } if(f==3) { sm[cr][0]=vl[cr][0]=b; sm[cr][1]=vl[cr][1]=a; for(int i=2;i<M;i++)sm[cr][i]=vl[cr][i]=0; } } }w[N]; bool isrt(int cr){return c[fa[cr]][0]!=cr&&c[fa[cr]][1]!=cr;} void pshp(int cr) { for(int i=0;i<M;i++)sm[cr][i]=sm[ls][i]+sm[rs][i]+vl[cr][i]; } void Rev(int cr){if(rev[cr]){rev[cr]=0;rev[ls]^=1;rev[rs]^=1;swap(ls,rs);}} void rotate(int x) { int y=fa[x],z=fa[y],d=(x==c[y][1]); if(!isrt(y))c[z][y==c[z][1]]=x; fa[x]=z; fa[y]=x; fa[c[x][!d]]=y; c[y][d]=c[x][!d]; c[x][!d]=y; pshp(y);pshp(x); } void splay(int x) { sta[top=1]=x; for(int cr=x;!isrt(cr);cr=fa[cr])sta[++top]=fa[cr]; for(int i=top;i;i--)Rev(sta[i]); int y,z; while(!isrt(x)) { y=fa[x];z=fa[y]; if(!isrt(y)) ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y); rotate(x); } } void access(int cr) { for(int t=0;cr;splay(cr),rs=t,pshp(cr),t=cr,cr=fa[cr]);//pshp()!!! } void mkrt(int cr) { access(cr);splay(cr);rev[cr]^=1; } void link(int x,int y) { mkrt(x);fa[x]=y; } void cut(int x,int y) { mkrt(x);access(y);splay(y); fa[x]=c[y][0]=0;pshp(y); } void mdfy(int cr,int f,db a,db b) { splay(cr); w[cr]=Node(f,a,b);w[cr].cz(cr); } db cal(int cr,db x) { db ret=0,ml=1; for(int i=0;i<M;i++,ml*=x) ret+=sm[cr][i]*ml/jc[i]; return ret; } int fnd(int cr) { while(!isrt(cr))cr=fa[cr];return cr; } void print(db x) { bool fx=0;int t=0; if(x<1){fx=1;while(x<1)x*=10,t++;} if(x>=10){while(x>=10)x/=10,t++;} printf("%.8fe%c%03d\n",x,fx?'-':'+',t); } int main() { jc[0]=1;for(int i=1;i<M;i++)jc[i]=jc[i-1]*i; n=rdn();int m=rdn();char ch[15];scanf("%s",ch); for(int i=1;i<=n;i++) w[i].f=rdn(),scanf("%lf%lf",&w[i].a,&w[i].b),w[i].cz(i),pshp(i);//pshp for sm[] int u,v;db a,b; while(m--) { scanf("%s",ch); if(ch[0]=='a'){u=rdn()+1;v=rdn()+1;link(u,v);} if(ch[0]=='d'){u=rdn()+1;v=rdn()+1;cut(u,v);} if(ch[0]=='m'){u=rdn()+1;v=rdn();scanf("%lf%lf",&a,&b);mdfy(u,v,a,b);} if(ch[0]=='t') { u=rdn()+1;v=rdn()+1;scanf("%lf",&a); mkrt(u);access(v);splay(v); if(fnd(u)!=v)puts("unreachable"); else print(cal(v,a)); } } return 0; }