BZOJ5020 [THUWC 2017]在美妙的数学王国中畅游LCT

题意很明显是要用LCT来维护森林 难点在于如何处理函数之间的关系 我们可以根据题目给的提示关于泰勒展开的式子 将三种函数变成泰勒展开的形式

因为\(x∈[0,1]\) 所以我们可以将三个函数在\(x_0=0\)处展开

\(sin(ax+b)=sin(b)+\frac{acos(b)x}{1!}+\frac{-a^2sin(b)x^2}{2!}+\frac{-a^3cos(b)x^3}{3!}+⋯\)

\(e^{ax+b}=e^b+\frac{ae^bx}{1!}+\frac{a^2e^bx^2}{2!}+\frac{a^3e^bx^3}{3!}+⋯\)

\(ax+b=b+\frac{ax}{1!}+\frac{0x^2}{2!}+\frac{0x^3}{3!}+⋯\)

\(splay\)合并时暴力合并每一位 我处理到\(x^{13}\)就可以\(AC\)

#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 1000000007
#define ll long long
#define mk make_pair
#define pb push_back
#define fi fisrt
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
const int INF = 0x7fffffff;
const int N=1e5+5;
const int D=13; 
inline int read(){
    int x=0,rev=0,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return rev?-x:x;
}
int n,m,cnt,c[N][2],fa[N],q[N],rev[N];
char ss[D];
double tmp[4],fac[D];
struct data{
	int type;
	double a,b,T[D],v[D];
	void calc(){
		if(type==1){
			double ga=a;
			T[0]=tmp[0]=sin(b),tmp[1]=cos(b),tmp[2]=-tmp[0],tmp[3]=-tmp[1];
			for(int i=1;i<D;i++) T[i]=tmp[i%4]*ga,ga*=a;
		}		
		else if(type==2){
			double eb=exp(b),ga=a;
			T[0]=eb;
			for(int i=1;i<D;i++) T[i]=eb*ga,ga*=a;
		}
		else {
			T[0]=b,T[1]=a;
			for(int i=2;i<D;i++) T[i]=0;
		}
	}
}s[N];
void update(int x){
	for(int i=0;i<D;i++) s[x].v[i]=s[c[x][0]].v[i]+s[c[x][1]].v[i]+s[x].T[i]; 
}
void pushdown(int x){
	int l=c[x][0],r=c[x][1];
	if(rev[x]){
		rev[x]^=1,rev[l]^=1,rev[r]^=1;
		swap(c[x][0],c[x][1]);
	}
}
bool isroot(int x){
	return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
}
void rotate(int x){
	int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
	if(!isroot(y)) c[z][c[z][1]==y]=x;
	fa[x]=z,fa[y]=x,fa[c[x][r]]=y;
	c[y][l]=c[x][r],c[x][r]=y;
	update(y),update(x);
} 
void splay(int x){
	cnt=0,q[++cnt]=x;
	for(int i=x;!isroot(i);i=fa[i]) q[++cnt]=fa[i];
	for(int i=cnt;i;--i) pushdown(q[i]);
	while(!isroot(x)){
		int y=fa[x],z=fa[y];
		if(!isroot(y)){
			if(c[y][0]==x^c[z][0]==y) rotate(x);
			else rotate(y);
		}
		rotate(x);
	}
}
void access(int x){
	for(int t=0;x;t=x,x=fa[x])
		splay(x),c[x][1]=t,update(x);
}
void makeroot(int x){
	access(x),splay(x),rev[x]^=1;
}
int find(int x){
	access(x),splay(x);while(c[x][0]) x=c[x][0];
	return x; 
}
void cut(int x,int y){
	makeroot(x),access(y),splay(y);
	if(c[y][0]==x) c[y][0]=fa[x]=0;
}
void link(int x,int y){
	makeroot(x),fa[x]=y;
}
int main(){
#ifdef Devil_Gary
	freopen("in.txt","r",stdin);
#endif
	n=read(),m=read(),scanf("%s",ss),fac[0]=1;
	for(int i=1;i<D;i++) fac[i]=fac[i-1]*i;
	for(int i=1;i<=n;i++) s[i].type=read(),scanf("%lf%lf",&s[i].a,&s[i].b),s[i].calc();
	for(int i=1;i<=m;i++){
		int u,v,c;double x,y,ans;
		scanf("%s",ss);
		if(ss[0]=='a'){
			u=read()+1,v=read()+1,link(u,v);
		}
		else if(ss[0]=='d'){
			u=read()+1,v=read()+1,cut(u,v);
		}
		else if(ss[0]=='m'){
			c=read()+1,splay(c),s[c].type=read(),scanf("%lf %lf",&s[c].a,&s[c].b);
			s[c].calc(),update(c);
		}
		else{
			u=read()+1,v=read()+1,scanf("%lf",&x);
			if(find(u)!=find(v)){
				printf("unreachable\n");
				continue;
			}
			makeroot(u),access(v),splay(v),y=x,ans=s[v].v[0];
			for(int j=1;j<D;j++,y*=x) ans+=y*s[v].v[j]/fac[j];
			printf("%.8le\n",ans); 
		} 
	}
}
posted @ 2018-04-16 11:36  Devil_Gary  阅读(186)  评论(0编辑  收藏  举报