$ color{#0066ff}{ 题目描述 }$
学渣小R被大学的数学课程虐得生活不能自理,微积分的成绩曾是他在教室里上的课的最低分。然而他的某位陈姓室友却能轻松地在数学考试中得到满分。为了提升自己的数学课成绩,有一天晚上(在他睡觉的时候),他来到了数学王国。
数学王国中,每个人的智商可以用一个属于([0,1])的实数表示。数学王国中有(n)个城市,编号从(0)到(n-1),这些城市由若干座魔法桥连接。每个城市的中心都有一个魔法球,每个魔法球中藏有一道数学题。每个人在做完这道数学题之后都会得到一个在([0,1])区间内的分数。一道题可以用一个从([0,1])映射到([0,1])的函数(f(x))表示。若一个人的智商为(x),则他做完这道数学题之后会得到(f(x))分。函数fff有三种形式:
- 正弦函数(sin(a x + b) (a in [0,1], b in [0,pi],a+bin[0,pi]))
- 指数函数(e^{ax+b} (ain [-1,1], bin [-2,0], a+bin [-2,0]))
- 一次函数(ax + b (ain [-1,1],bin[0,1],a+bin [0,1]))
数学王国中的魔法桥会发生变化,有时会有一座魔法桥消失,有时会有一座魔法桥出现。但在任意时刻,只存在至多一条连接任意两个城市的简单路径(即所有城市形成一个森林)。在初始情况下,数学王国中不存在任何的魔法桥。
数学王国的国王拉格朗日很乐意传授小R数学知识,但前提是小R要先回答国王的问题。这些问题具有相同的形式,即一个智商为(x)的人从城市(u)旅行到城市(v)(即经过(u)到(v)这条路径上的所有城市,包括(u)和(v))且做了所有城市内的数学题后,他所有得分的总和是多少。
(color{#0066ff}{输入格式})
第一行两个正整数 (n,m)和一个字符串(type)。表示数学王国中共有(n)座城市,发生了(m)个事件,该数据的类型为(type)。(type)字符串是为了能让大家更方便地获得部分分,你可能不需要用到这个输入。其具体含义在【限制与约定】中有解释。
接下来(n)行,第(i)行表示初始情况下编号为 (i) 的城市的魔法球中的函数。一个魔法用一个整数 (f) 表示函数的类型,两个实数 (a,b) 表示函数的参数,若
- (f=1),则函数为(f(x)=sin(ax+b)(a in [0,1], b in [0,pi],a+bin[0,pi]))
- (f=2),则函数为(f(x)=e^{ax+b}(ain[-1,1],bin[-2,0],a+bin[-2,0]))
- (f=3),则函数为(f(x)=ax+b(ain[-1,1],bin[0,1],a+bin[0,1]))
接下来 (m) 行,每行描述一个事件,事件分为四类。
appear u v
表示数学王国中出现了一条连接(u)和(v)这两座城市的魔法桥((0le u,v < n, u e v)),保证连接前(u)和(v)这两座城市不能互相到达。disappear u v
表示数学王国中连接(u)和(v)这两座城市的魔法桥消失了,保证这座魔法桥是存在的。magic c f a b
表示城市(c)的魔法球中的魔法变成了类型为(f),参数为(a,b)的函数travel u v x
表示询问一个智商为(x)的人从城市(u)旅行到城市(v)(即经过(u)到(v)这条路径上的所有城市,包括(u)和(v))后,他得分的总和是多少。若无法从(u)到达(v),则输出一行一个字符串unreachable
。
(color{#0066ff}{输出格式})
对于每个询问,输出一行实数,表示得分的总和。
(color{#0066ff}{输入样例})
3 7 C1
1 1 0
3 0.5 0.5
3 -0.5 0.7
appear 0 1
travel 0 1 0.3
appear 0 2
travel 1 2 0.5
disappear 0 1
appear 1 2
travel 1 2 0.5
(color{#0066ff}{输出样例})
9.45520207e-001
1.67942554e+000
1.20000000e+000
(color{#0066ff}{数据范围与提示})
对于100%的数据,(1le nle 100000, 1le m le 200000)
本题共有20个数据点,每个数据点5分。
测试点 | (n) | (m) | 数据类型 |
---|---|---|---|
(1) | (leq 100) | (leq 200) | C1 |
(2-5) | (leq 100000) | (leq 200000) | A0 |
(6) | null | null | B0 |
(7-8) | null | null | D0 |
(9-14) | null | null | A1 |
(15-17) | null | null | C1 |
(18-20) | null | null | D1 |
数据类型的含义:
A:不存在 disappear
事件,且所有appear
事件中的(u=v-1)
B:不存在 disappear
事件
C:所有的 travel
事件经过的城市总数 (le 5000000)(不可到达的城市对不计入在内)
D:无限制
0:所有 travel
事件中,(x=1)(即所有人的智商均为(1))
1:无限制
【评分标准】
如果你的答案与标准答案的相对误差在(10^{-7})以内或绝对误差在(10^{-7})以内,则被判定为正确。
如果你的所有答案均为正确,则得满分,否则得0分。
请注意输出格式:每行输出一个答案,答案只能为 unreachable
或者一个实数(建议使用科学计数法表示)。每行的长度不得超过50。错误输出格式会被判定为0分。
【小R教你学数学】
若函数(f(x))的(n)阶导数在([a,b])区间内连续,则对(f(x))在(x_0(x_0in[a,b]))处使用(n)次拉格朗日中值定理可以得到带拉格朗日余项的泰勒展开式
(f(x)=f(x_0)+frac{f'(x_0)(x-x_0)}{1!}+frac{f''(x_0)(x-x_0)^2}{2!}+ cdots +frac{f^{(n-1)}(x_0)(x-x_0)^{n-1}}{(n-1)!}+frac{f^{(n)}(xi)(x-x_0)^n}{n!},xin[a,b])
其中,当(x>x_0)时,(xiin[x_0,x])。当(x<x_0)时,(xiin[x,x_0])。
(f^{(n)})表示函数(f)的(n)阶导数
(color{#0066ff}{题解})
根据题目显然我们要写一个LCT
然后维护这些函数的和
但是这些函数没有办法直接相加,于是良心出题人让我们进行泰勒展开
然后就成了一个多项式,就可以加了
据说在0.5处展开只用展开8项就行
蒟蒻在0处展开了11项。。。
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 2e5 + 10;
const int inf = 0x7fffffff;
struct Tylar{
double a[12];
Tylar() { memset(a, 0, sizeof a); }
Tylar(int tp, double aa, double bb) {
if(tp == 1) {
double now = 1, x = sin(bb), y = cos(bb);
for(int i = 1; i <= 11; i++, x = -x, now *= aa, std::swap(x, y)) a[i] = now * x;
}
if(tp == 2) {
bb = exp(bb);
for(int i = 1; i <= 11; i++, bb *= aa) a[i] = bb;
}
if(tp == 3) {
*this = Tylar();
a[1] = bb, a[2] = aa;
}
}
friend Tylar operator + (const Tylar &a,const Tylar &b) {
Tylar c;
for(int i = 1; i <= 11; i++) c.a[i] = a.a[i] + b.a[i];
return c;
}
double getans(double x) {
double ans = 0;
for(int i = 11; i >= 1; i--) ans = a[i] + ans * x / i;
return ans;
}
};
struct LCT {
protected:
struct node {
node *ch[2], *fa;
int rev;
Tylar val, tot;
node(int rev = 0): rev(rev) { ch[0] = ch[1] = fa = NULL; }
bool ntr() { return fa && (fa->ch[1] == this || fa->ch[0] == this); }
void trn() { std::swap(ch[0], ch[1]), rev ^= 1; }
bool isr() { return fa->ch[1] == this; }
void upd(){
tot = val;
if(ch[0]) tot = tot + ch[0]->tot;
if(ch[1]) tot = tot + ch[1]->tot;
}
void dwn() {
if(!rev) return;
if(ch[0]) ch[0]->trn();
if(ch[1]) ch[1]->trn();
rev = 0;
}
}pool[maxn];
void rot(node* x) {
node *y = x->fa, *z = y->fa;
bool k = x->isr(); node *w = x->ch[!k];
if(y->ntr()) z->ch[y->isr()] = x;
(x->ch[!k] = y)->ch[k] = w;
(y->fa = x)->fa = z;
if(w) w->fa = y;
y->upd(), x->upd();
}
void splay(node *o) {
static node *st[maxn];
int top;
st[top = 1] = o;
while(st[top]->ntr()) st[top + 1] = st[top]->fa, top++;
while(top) st[top--]->dwn();
while(o->ntr()) {
if(o->fa->ntr()) rot(o->isr() ^ o->fa->isr()? o : o->fa);
rot(o);
}
}
void access(node *x) {
for(node *y = NULL; x; x = (y = x)->fa)
splay(x), x->ch[1] = y, x->upd();
}
void makeroot(node *x) { access(x), splay(x), x->trn(); }
node *findroot(node *o){
access(o), splay(o);
while(o->dwn(), o->ch[0]) o = o->ch[0];
return splay(o), o;
}
public:
void link(int l, int r) {
node *x = pool + l, *y = pool + r;
makeroot(x), x->fa = y;
}
void cut(int l, int r) {
node *x = pool + l, *y = pool + r;
makeroot(x), access(y), splay(y);
y->ch[0] = x->fa = NULL;
y->upd();
}
void change(int id, int tp, double a, double b) {
node *o = pool + id;
splay(o);
o->val = Tylar(tp, a, b);
o->upd();
}
Tylar query(int l, int r) {
node *x = pool + l, *y = pool + r;
makeroot(x), access(y), splay(y);
return y->tot;
}
bool init(int l, int r) { return findroot(pool + l) == findroot(pool + r); }
}s;
char getch() {
char ch;
while(!isalpha(ch = getchar()));
return ch;
}
int main(){
int n = in(), m = in(); in();
double a, b;
for(int i = 0; i <= n - 1; i++) {
int tp = in();
scanf("%lf%lf", &a, &b);
s.change(i, tp, a, b);
}
int c, d;
while(m --> 0) {
char ch = getch();
if(ch == 'a') s.link(in(), in());
if(ch == 'd') s.cut(in(), in());
if(ch == 'm') {
c = in(), d = in();
scanf("%lf%lf", &a, &b);
s.change(c, d, a, b);
}
if(ch == 't') {
c = in(), d = in();
scanf("%lf", &a);
if(s.init(c, d)) printf("%.10f
", s.query(c, d).getans(a));
else puts("unreachable");
}
}
return 0;
}