loj2289 [THUWC 2017]在美妙的数学王国中畅游(LCT+Taylor展开)

link

题目大意:

你需要维护一个树

每个点都有个sin(ax+b)或exp(ax+b)或ax+b

你需要维护一些操作:连边、删边、修改某个点的初等函数、询问某条树链上所有函数带入某个值后权值和或不连通

保证x在[0,1],带入后得到的值在[0,1]

允许精度误差在1e-7

题解:

由于sin函数和exp函数不是多项式函数,比较cd,并且题目要求我们求的值比较小,我们可以对函数在0.5处求泰勒展开,然后每个点就维护了一个多项式函数

多项式函数加减后还是多项式函数,就可以通过Link-Cut Tree维护树的形态同时维护函数相加,然后直接代入求值就行

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

struct poly
{
	double a[10];
	poly() { }
	double getval(double x);
	void output();
} val[233333], sum[233333];

const double fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int ch[233333][2], fa[233333], st[233333], n, m;
char type[233], tmp[233];
bool lazy[233333];

poly operator+(const poly &a, const poly &b)
{
	poly ans;
	ans.a[0] = a.a[0] + b.a[0];
	ans.a[1] = a.a[1] + b.a[1];
	ans.a[2] = a.a[2] + b.a[2];
	ans.a[3] = a.a[3] + b.a[3];
	ans.a[4] = a.a[4] + b.a[4];
	ans.a[5] = a.a[5] + b.a[5];
	ans.a[6] = a.a[6] + b.a[6];
	ans.a[7] = a.a[7] + b.a[7];
	ans.a[8] = a.a[8] + b.a[8];
	ans.a[9] = a.a[9] + b.a[9];
	return ans;
}

double poly::getval(double x)
{
	return ((((((((a[9] * x + a[8]) * x + a[7]) * x + a[6]) * x + a[5]) * x + a[4]) * x + a[3]) * x + a[2]) * x + a[1]) * x + a[0];
}

void poly::output()
{
	for (int i = 0; i < 10; i++)
	{
		if (a[i] >= 0) printf("+");
		printf("%f", a[i]);
		for (int j = 0; j < i; j++) printf(" * x");
	}
}

poly getpoly(int type, double k, double b)
{
	if (type == 1) // y = sin(k * x + b)
	{
		poly ans; double tmp = 1, sinval = sin(k * 0.5 + b), cosval = cos(k * 0.5 + b);
		ans.a[0] =  tmp * sinval / fac[0]; tmp *= k;
		ans.a[1] =  tmp * cosval / fac[1]; tmp *= k;
		ans.a[2] = -tmp * sinval / fac[2]; tmp *= k;
		ans.a[3] = -tmp * cosval / fac[3]; tmp *= k;
		ans.a[4] =  tmp * sinval / fac[4]; tmp *= k;
		ans.a[5] =  tmp * cosval / fac[5]; tmp *= k;
		ans.a[6] = -tmp * sinval / fac[6]; tmp *= k;
		ans.a[7] = -tmp * cosval / fac[7]; tmp *= k;
		ans.a[8] =  tmp * sinval / fac[8]; tmp *= k;
		ans.a[9] =  tmp * cosval / fac[9];
		return ans;
	}
	if (type == 2) // y = exp(k * x + b)
	{
		poly ans; double tmp = 1, expval = exp(k * 0.5 + b);
		ans.a[0] = tmp * expval / fac[0]; tmp *= k;
		ans.a[1] = tmp * expval / fac[1]; tmp *= k;
		ans.a[2] = tmp * expval / fac[2]; tmp *= k;
		ans.a[3] = tmp * expval / fac[3]; tmp *= k;
		ans.a[4] = tmp * expval / fac[4]; tmp *= k;
		ans.a[5] = tmp * expval / fac[5]; tmp *= k;
		ans.a[6] = tmp * expval / fac[6]; tmp *= k;
		ans.a[7] = tmp * expval / fac[7]; tmp *= k;
		ans.a[8] = tmp * expval / fac[8]; tmp *= k;
		ans.a[9] = tmp * expval / fac[9];
		return ans;
	}
	// y = k * x + b
	poly ans;
	ans.a[0] = k / 2 + b;
	ans.a[1] = k;
	ans.a[2] = ans.a[3] = ans.a[4] = ans.a[5] = ans.a[6] = ans.a[7] = ans.a[8] = ans.a[9] = 0;
	return ans;
}

bool nroot(int x) { return ch[fa[x]][0] == x || ch[fa[x]][1] == x; }
void pushup(int x) { sum[x] = sum[ch[x][0]] + sum[ch[x][1]] + val[x]; }
void rev(int x) { swap(ch[x][0], ch[x][1]), lazy[x] ^= 1; }
void pushdown(int x) { if (lazy[x]) { if (ch[x][0]) rev(ch[x][0]); if (ch[x][1]) rev(ch[x][1]); lazy[x] = 0; } }
void rotate(int x)
{
	int y = fa[x], z = fa[y], k = (ch[y][1] == x), w = ch[x][k ^ 1];
	if (nroot(y)) { ch[z][ch[z][1] == y] = x; } ch[x][k ^ 1] = y, ch[y][k] = w;
	if (w) { fa[w] = y; } fa[y] = x, fa[x] = z, pushup(y), pushup(x);
}
void splay(int x)
{
	int y = x, top = 0; st[++top]= y; while (nroot(y)) { st[++top] = y = fa[y]; } while (top > 0) pushdown(st[top--]);
	while (nroot(x)) { int y = fa[x], z = fa[y]; if (nroot(y)) rotate((ch[y][1] == x) ^ (ch[z][1] == y) ? x : y); rotate(x); }
}
void access(int x) { for (int y = 0; x > 0; x = fa[y = x]) splay(x), ch[x][1] = y, pushup(x); }
void makert(int x) { access(x), splay(x), rev(x); }
int findrt(int x) { access(x), splay(x); while (ch[x][0]) pushdown(x), x = ch[x][0]; return x; }
void link(int x, int y) { makert(x); if (findrt(y) != x) fa[x] = y; }
void cut(int x, int y) { makert(x); if (findrt(y) == x && fa[x] == y && ch[x][1] == 0) ch[y][0] = fa[x] = 0, pushup(y); }

int main()
{
	scanf("%d%d", &n, &m); scanf("%s", type);
	double a, b;
	for (int t, i = 1; i <= n; i++)
		scanf("%d%lf%lf", &t, &a, &b), val[i] = sum[i] = getpoly(t, a, b);
	for (int u, v, c, f, i = 1; i <= m; i++)
	{
		scanf("%s", tmp);
		if (!strcmp(tmp, "appear")) scanf("%d%d", &u, &v), link(u + 1, v + 1);
		if (!strcmp(tmp, "disappear")) scanf("%d%d", &u, &v), cut(u + 1, v + 1);
		if (!strcmp(tmp, "travel"))
		{
			double x;
			scanf("%d%d%lf", &u, &v, &x), u++, v++;
			makert(u);
			if (findrt(v) != u) puts("unreachable");
			else
			{
				printf("%.10f\n", sum[v].getval(x - 0.5));
			}
		}
		if (!strcmp(tmp, "magic"))
		{
			double a, b;
			scanf("%d%d%lf%lf", &c, &f, &a, &b), c++;
			splay(c), val[c] = getpoly(f, a, b), pushup(c);
		}
	}
	return 0;
}
posted @ 2019-03-08 15:03  ghj1222  阅读(170)  评论(0编辑  收藏  举报