Submit: 167 Solved: 76
Description
数字和数学规律主宰着这个世界。
机器的运转,
生命的消长,
宇宙的进程,
这些神秘而又美妙的过程无不可以用数学的语言展现出来。
这印证了一句古老的名言:
“学好数理化,走遍天下都不怕。”
学渣小R被大学的数学课程虐得生活不能自理,微积分的成绩曾是他在教室里上的课的最低分。然而他的某位陈姓室友却能轻松地在数学考试中得到满分。为了提升自己的数学课成绩,有一天晚上(在他睡觉的时候),他来到了数学王国。
数学王国中,每个人的智商可以用一个属于 [0,1]的实数表示。数学王国中有 n 个城市,编号从 0 到 n−1 ,这些城市由若干座魔法桥连接。每个城市的中心都有一个魔法球,每个魔法球中藏有一道数学题。每个人在做完这道数学题之后都会得到一个在 [0,1] 区间内的分数。一道题可以用一个从 [0,1] 映射到 [0,1]的函数 f(x) 表示。若一个人的智商为 x ,则他做完这道数学题之后会得到 f(x)分。函数 f有三种形式:
正弦函数 sin(ax+b) (a∈[0,1],b∈[0,π],a+b∈[0,π])
指数函数 e^(ax+b) (a∈[−1,1],b∈[−2,0],a+b∈[−2,0])
一次函数 ax+b (a∈[−1,1],b∈[0,1],a+b∈[0,1]
数学王国中的魔法桥会发生变化,有时会有一座魔法桥消失,有时会有一座魔法桥出现。但在任意时刻,只存在至多一条连接任意两个城市的简单路径(即所有城市形成一个森林)。在初始情况下,数学王国中不存在任何的魔法桥。
数学王国的国王拉格朗日很乐意传授小R数学知识,但前提是小R要先回答国王的问题。这些问题具有相同的形式,即一个智商为 x 的人从城市 u 旅行到城市 v(即经过 u 到 v 这条路径上的所有城市,包括 u和 v )且做了所有城市内的数学题后,他所有得分的总和是多少。
Input
第一行两个正整数 n,m 和一个字符串 type 。
表示数学王国中共有 n 座城市,发生了 m 个事件,该数据的类型为 type 。
typet 字符串是为了能让大家更方便地获得部分分,你可能不需要用到这个输入。
其具体含义在【数据范围与提示】中有解释。
接下来 n 行,第 i 行表示初始情况下编号为 i 的城市的魔法球中的函数。
一个魔法用一个整数 f表示函数的类型,两个实数 a,b 表示函数的参数,若
f=1,则函数为 f(x)=sin(ax+b)(a∈[0,1],b∈[0,π],a+b∈[0,π])
f=2,则函数为 f(x)=e^(ax+b)(a∈[−1,1],b∈[−2,0],a+b∈[−2,0])
f=3,则函数为 f(x)=ax+b(a∈[−1,1],b∈[0,1],a+b∈[0,1])
接下来 m行,每行描述一个事件,事件分为四类。
appear u v 表示数学王国中出现了一条连接 u 和 v 这两座城市的魔法桥 (0≤u,v<n,u≠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。
1≤n≤100000,1≤m≤200000
Output
对于每个询问,输出一行实数,表示得分的总和。
Sample Input
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
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
Sample Output
9.45520207e-001
1.67942554e+000
1.20000000e+000
1.67942554e+000
1.20000000e+000
Solution
LCT+泰勒展开。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const int N=100100; int n,q,son[N][2],fa[N],rev[N],Stack[N]; char s[20]; double frac[20],Sum[N][16],Tree[N][16]; bool isRoot(int x) { return (son[fa[x]][0]!=x)&&(son[fa[x]][1]!=x);} void update(int x) { for (int i=0;i<=15;i++) Sum[x][i]=Sum[son[x][0]][i]+Sum[son[x][1]][i]+Tree[x][i]; } void pushdown(int x) { if (rev[x]) { if (son[x][0]) rev[son[x][0]]^=1; if (son[x][1]) rev[son[x][1]]^=1; swap(son[x][0],son[x][1]); rev[x]=0; } } void Rotate(int x) { int y=fa[x],z=fa[y],l,r; if (son[y][0]==x) l=0;else l=1; r=l^1; if (!isRoot(y)) { if (son[z][0]==y) son[z][0]=x;else son[z][1]=x; } fa[x]=z;fa[y]=x;fa[son[x][r]]=y; son[y][l]=son[x][r];son[x][r]=y; update(y);update(x); } void splay(int x) { int top=0;Stack[++top]=x; for (int i=x;!isRoot(i);i=fa[i]) Stack[++top]=fa[i]; for (;top;top--) pushdown(Stack[top]); while (!isRoot(x)) { int y=fa[x],z=fa[y]; if (!isRoot(y)) { if ((son[z][0]==y)^(son[y][0]==x)) Rotate(x); else Rotate(y); } Rotate(x); } } void access(int x) { for (int i=0;x;i=x,x=fa[x]) { splay(x); son[x][1]=i; update(x); } } void MakeRoot(int x) { access(x); splay(x); rev[x]^=1; } int compuse(int x,int y) { MakeRoot(x); access(y); splay(y); return y; } int GetRoot(int x) { access(x); splay(x); while (son[x][0]) x=son[x][0]; return x; } void link(int x,int y) { MakeRoot(x); fa[x]=y; } void cut(int x,int y) { MakeRoot(x); access(y); splay(y); son[y][0]=fa[x]=0; update(y); } void query(int x,int y,double X) { if (GetRoot(x)!=GetRoot(y)) { puts("unreachable");return;} int id=compuse(x,y); double ans=0.0,P=1.0; X-=0.5; for (int i=0;i<=15;i++) { ans+=P*Sum[id][i]; P=P*X; } printf("%.10le\n",ans); } void calc(int id,int f,double a,double b) { splay(id); for (int i=0;i<=15;i++) Tree[id][i]=0; if (f==1) { double X=a*0.5+b; Tree[id][0]=sin(X); Tree[id][1]=cos(X)*a; for (int i=2;i<=15;i++) Tree[id][i]=-Tree[id][i-2]*a*a; for (int i=0;i<=15;i++) Tree[id][i]/=frac[i]; } if (f==2) { double X=1,Y=a*0.5+b; for (int i=0;i<=15;i++) Tree[id][i]=exp(Y)*X/frac[i],X=X*a; } if (f==3) { Tree[id][0]=b+a*0.5; Tree[id][1]=a; } update(id); } void pre() { frac[0]=1.0; for (int i=1;i<=15;i++) frac[i]=frac[i-1]*i; } int main() { scanf("%d%d%s",&n,&q,s); pre(); for (int i=1;i<=n;i++) { int id;double x,y; scanf("%d%lf%lf",&id,&x,&y); calc(i,id,x,y); } while (q--) { int x,y;double a,b; scanf("%s",s); if (s[0]=='a') { scanf("%d%d",&x,&y);link(++x,++y);} if (s[0]=='d') { scanf("%d%d",&x,&y);cut(++x,++y);} if (s[0]=='m') { scanf("%d%d%lf%lf",&x,&y,&a,&b);calc(++x,y,a,b);} if (s[0]=='t') { scanf("%d%d%lf",&x,&y,&a);query(++x,++y,a);} } return 0; } |
Orz!!!!!!