[LOJ2289][THUWC2017]在美妙的数学王国中畅游:Link-Cut Tree+泰勒展开

分析

又有毒瘤出题人把数学题出在树上了。

根据泰勒展开,有:

\[e^x=1+\frac{1}{1!}x+\frac{1}{2!}x^2+\frac{1}{3!}x^3+... \]

\[sin(x)=x-\frac{1}{3!}x^3+\frac{1}{5!}x^5-... \]

然而题目里\(x\)的位置是一个\(ax+b\)怎么办啊?直接根据二项式定理暴力展开就好了。

题目中要求支持加边删边,可以想到肯定是LCT。维护一下链上所有结点各次项系数和,查询时直接利用整条链的信息计算答案即可。

计算到\(16\)次项精度就没啥问题了。(其实是为了凑个整)

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}

const int MAXN=100005;
const int MAXM=200005;
int n,m,top,sta[MAXN];
char opt[15];
double fac[20],c[20][20],powk[20],powb[20];
struct lct{
	int fa,ch[2];
	int opt;
	double k,b;
	double v[20];
	double sum[20];
	bool tag;
}a[MAXN];

inline void pre_process(){
	fac[0]=1;
	rin(i,1,16) fac[i]=fac[i-1]*i;
	c[0][0]=1;
	rin(i,1,16) rin(j,0,i){
		c[i][j]=c[i-1][j];
		if(j) c[i][j]+=c[i-1][j-1];
	}
}

#define lc a[x].ch[0]
#define rc a[x].ch[1]
inline bool isroot(int x){
	return a[a[x].fa].ch[0]!=x&&a[a[x].fa].ch[1]!=x;
}

inline void pushup(int x){
	rin(i,0,16) a[x].sum[i]=a[x].v[i]+a[lc].sum[i]+a[rc].sum[i];
}

inline void pushr(int x){
	std::swap(lc,rc);
	a[x].tag^=1;
}

inline void pushdown(int x){
	if(!a[x].tag) return;
	if(lc) pushr(lc);
	if(rc) pushr(rc);
	a[x].tag=0;
}

inline void info(int x){
	memset(a[x].v,0,sizeof a[x].v);
	if(a[x].opt==1){
		powk[0]=powb[0]=1;
		rin(i,1,16){
			powk[i]=powk[i-1]*a[x].k;
			powb[i]=powb[i-1]*a[x].b;
		}
		int pn=1;
		for(int i=1;i<=16;i+=2){
			rin(j,0,i){
				a[x].v[j]+=pn*powk[j]*powb[i-j]*c[i][j]/fac[i];
			}
			pn=-pn;
		}
	}
	else if(a[x].opt==2){
		powk[0]=powb[0]=1;
		rin(i,1,16){
			powk[i]=powk[i-1]*a[x].k;
			powb[i]=powb[i-1]*a[x].b;
		}
		rin(i,0,16){
			rin(j,0,i){
				a[x].v[j]+=powk[j]*powb[i-j]*c[i][j]/fac[i];
			}
		}
	}
	else{
		a[x].v[1]=a[x].k;
		a[x].v[0]=a[x].b;
	}
	pushup(x);
}

inline void rotate(int x){
	int y=a[x].fa,z=a[y].fa,f=(a[y].ch[1]==x),g=a[x].ch[f^1];
	if(!isroot(y)) a[z].ch[a[z].ch[1]==y]=x;
	a[x].ch[f^1]=y;
	a[y].ch[f]=g;
	if(g) a[g].fa=y;
	a[y].fa=x;
	a[x].fa=z;
	pushup(y);
}

inline void splay(int x){
	int y=x,z=0;
	top=1,sta[1]=y;
	while(!isroot(y)) sta[++top]=y=a[y].fa;
	while(top) pushdown(sta[top--]);
	while(!isroot(x)){
		y=a[x].fa,z=a[y].fa;
		if(!isroot(y)){
			if((a[y].ch[0]==x)==(a[z].ch[0]==y)) rotate(y);
			else rotate(x);
		}
		rotate(x);
	}
	pushup(x);
}

inline void access(int x){
	for(int y=0;x;x=a[y=x].fa){
		splay(x);
		rc=y;
		pushup(x);
	}
}

inline void makeroot(int x){
	access(x);
	splay(x);
	pushr(x);
}

inline int findroot(int x){
	access(x);
	splay(x);
	while(lc) x=lc;
	return x;
}

inline void split(int x,int y){
	makeroot(x);
	access(y);
	splay(y);
}

inline void link(int x,int y){
	makeroot(x);
	a[x].fa=y;
}

inline void cut(int x,int y){
	split(x,y);
	a[x].fa=0;
	a[y].ch[0]=0;
	pushup(y);
}

inline double query(int x,int y,double iq){
	split(x,y);
	double tt=1,ret=0;
	rin(i,0,16){
		ret+=a[y].sum[i]*tt;
		tt*=iq;
	}
	return ret;
}
#undef lc
#undef rc

int main(){
	pre_process();
	n=read(),m=read();
	scanf("%s",opt+1);
	rin(i,1,n){
		a[i].opt=read();
		scanf("%lf%lf",&a[i].k,&a[i].b);
		info(i);
	}
	while(m--){
		scanf("%s",opt+1);
		if(opt[1]=='a'){
			int x=read()+1,y=read()+1;
			link(x,y);
		}
		else if(opt[1]=='d'){
			int x=read()+1,y=read()+1;
			cut(x,y);
		}
		else if(opt[1]=='m'){
			int x=read()+1;a[x].opt=read();
			scanf("%lf%lf",&a[x].k,&a[x].b);
			getchar();
			splay(x);
			info(x);
		}
		else{
			int x=read()+1,y=read()+1;
			double iq;scanf("%lf",&iq);
			getchar();
			if(findroot(x)!=findroot(y)){
				printf("unreachable\n");
				continue;
			}
			printf("%.8le\n",query(x,y,iq));
		}
	}
	return 0;
}

posted on 2018-12-27 08:28  ErkkiErkko  阅读(109)  评论(0编辑  收藏

统计