Solution
PBS还是牛逼的啊。
把这些函数泰勒展开后只要维护多项式的系数就好了。。
我是真的菜,修改的时候没有MakeRoot。
还是不会LCT啊QAQ
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
const int N = 301010;
const int D = 15;
template<typename T>
inline T Max(T a, T b) {
return a < b ? b : a;
}
inline double sin_(double b, int n) {
n %= 4;
if (n == 0) return sin(b);
if (n == 1) return cos(b);
if (n == 2) return -sin(b);
return -cos(b);
}
inline double exp_(double b, int n) {
return exp(b);
}
int n, m, x, y, z, cnt;
double a, b;
char opt[100];
double fac[100];
double s[10];
namespace LCT {
struct node {
node *ch[2];
node *fa;
int rev;
double key[20];
double sum[20];
inline void PushUp(void) {
for (int i = 0; i <= D; i++)
sum[i] = key[i] + ch[0]->sum[i] + ch[1]->sum[i];
}
inline void PushDown(void) {
if (rev) {
swap(ch[0], ch[1]);
ch[0]->rev ^= 1;
ch[1]->rev ^= 1;
rev = 0;
}
}
inline void MakeFunc(int f, double a, double b) {
double A = 1;
for (int i = 0; i <= D; i++) key[i] = 0;
if (f == 1) {
s[0] = sin(b); s[1] = cos(b); s[2] = -sin(b); s[3] = -cos(b);
for (int i = 0; i <= D; i++) {
key[i] = s[i % 4] * A;
A *= a;
}
} else if (f == 2) {
for (int i = 0; i <= D; i++) {
key[i] = exp_(b, i) * A;
A *= a;
}
} else {
key[0] = b; key[1] = a;
}
PushUp();
}
inline double Val(double x) {
double ans = 0, X = 1;
for (int i = 0; i <= D; i++) {
ans += X * sum[i] / fac[i];
X *= x;
}
return ans;
}
};
node *null, *Tail;
node mem[N];
node *T[N], *sta[N];
int top;
inline node* NewNode(void) {
Tail->ch[0] = Tail->ch[1] = Tail->fa = null;
Tail->rev = 0;
for (int i = 0; i <= D; i++)
Tail->key[i] = Tail->sum[i] = 0;
return Tail++;
}
inline void Init(int n) {
Tail = mem; null = Tail++;
null->fa = null; null->rev = 0;
null->ch[0] = null->ch[1] = null;
for (int i = 0; i <= D; i++)
null->key[i] = null->sum[i] = 0;
int f; double a, b;
for (int i = 1; i <= n; i++) {
T[i] = NewNode();
scanf("%d%lf%lf", &f, &a, &b);
T[i]->MakeFunc(f, a, b);
}
}
inline bool IsRoot(node *x) {
return x->fa == null || (x->fa->ch[0] != x && x->fa->ch[1] != x);
}
inline void Rotate(node* x) {
node *y = x->fa, *z = y->fa;
int l = (y->ch[0] != x), r = l ^ 1;
if (!IsRoot(y) && z != null) {
if (z->ch[0] == y) z->ch[0] = x;
else z->ch[1] = x;
}
x->fa = z; y->fa = x; x->ch[r]->fa = y;
y->ch[l] = x->ch[r]; x->ch[r] = y;
y->PushUp(); x->PushUp();
}
inline void Down(node* x) {
if (!IsRoot(x)) Down(x->fa);
x->PushDown();
}
inline void Splay(node* x) {
Down(x);
while (!IsRoot(x)) {
node *y = x->fa, *z = y->fa;
if (!IsRoot(y)) {
if (y->ch[0] == x ^ z->ch[0] == y) Rotate(x);
else Rotate(y);
}
Rotate(x);
}
}
inline void Access(node* x) {
for (node *y = null; x != null; x = x->fa) {
Splay(x); x->ch[1] = y;
x->PushUp(); y = x;
}
}
inline void MakeRoot(node* x) {
Access(x); Splay(x); x->rev ^= 1;
}
inline void Link(node* x, node* y) {
MakeRoot(x); x->fa = y;
}
inline void Cut(node* x, node* y) {
MakeRoot(x); Access(y); Splay(y);
y->ch[0] = x->fa = null; y->PushUp();
}
inline double Query(node* x, node* y, double k) {
MakeRoot(x); Access(y); Splay(y);
return y->Val(k);
}
inline bool Check(node* x, node* y) {
static node *f1, *f2;
for (f1 = x; f1->fa != null; f1 = f1->fa);
for (f2 = y; f2->fa != null; f2 = f2->fa);
return f1 != f2;
}
}
int main(void) {
scanf("%d%d", &n, &m); gets(opt);
fac[0] = 1; for (int i = 1; i <= D; i++) fac[i] = fac[i - 1] * i;
LCT::Init(cnt = n);
for (int i = 1; i <= m; i++) {
scanf("%s%d%d", opt, &x, &y);
if (opt[0] == 'a') {
x++; y++;
LCT::Link(LCT::T[x], LCT::T[y]);
} else if (opt[0] == 'd') {
x++; y++;
LCT::Cut(LCT::T[x], LCT::T[y]);
} else if (opt[0] == 'm') {
scanf("%lf%lf", &a, &b); x++;
LCT::MakeRoot(LCT::T[x]);
LCT::T[x]->MakeFunc(y, a, b);
} else {
x++; y++;
scanf("%lf", &a);
if (Check(LCT::T[x], LCT::T[y])) puts("unreachable");
else printf("%.8e\n", LCT::Query(LCT::T[x], LCT::T[y], a));
}
}
return 0;
}