bzoj5020 [THUWC 2017]在美妙的数学王国中畅游

题目描述

题解:

这是一道数学题。

看一眼会发现暴力跑链会超时。

所以我们需要一些神奇的东西。

泰勒展开:

最后那个东西可以当作无穷小。

所以我们可以提一下:

所以我们用LCT维护树链的$f(x0)$前k阶导数就好了。

还有,这道题卡精,一定要将单点值放在函数里面。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100050
#define db double
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n,m,f[N];
char typ[10];
db dv[16],a[N],b[N];
/*
void F1(int x)
{
    if(!x)return ;
    db A = 1.0;
    db sn = sin(b),cs = cos(b);
    for(int i=0;i<=15;i++,A*=a)
    {
        if(i%4==0)f[x][i] = A*sn;
        else if(i%4==1)f[x][i] = A*cs;
        else if(i%4==2)f[x][i] = -A*sn;
        else f[x][i] = -A*cs;
    }
}
void F2(int x)
{
    if(!x)return ;
    db A = 1.0,ex = exp(b);
    for(int i=0;i<=15;i++,A*=a)
        f[x][i] = A*ex;
}
void F3(int x)
{
    if(!x)return ;
    f[x][0] = b;
    f[x][1] = a;
}
*/
struct LCT
{
    int fa[N],ch[N][2];
    db v[N][16];
    bool res[N];
    bool isroot(int x)
    {
        return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1];
    }
    void update(int u)
    {
        for(int i=0;i<=15;i++)
            v[u][i] = v[ch[u][0]][i] + v[ch[u][1]][i];
        if(f[u]==1)
        {
            db A = 1.0;
            db sn = sin(b[u]),cs = cos(b[u]);
            for(int i=0;i<=15;i++,A*=a[u])
            {
                if(i%4==0)v[u][i] += A*sn;
                else if(i%4==1)v[u][i] += A*cs;
                else if(i%4==2)v[u][i] -= A*sn;
                else v[u][i] -= A*cs;
            }
        }else if(f[u]==2)
        {
            db A = 1.0,ex = exp(b[u]);
            for(int i=0;i<=15;i++,A*=a[u])
                v[u][i] += A*ex;
        }else
        {
            v[u][0]+=b[u];
            v[u][1]+=a[u];
        }
    }
    void reser(int u)
    {
        res[u]^=1;
        swap(ch[u][0],ch[u][1]);
    }
    void pushdown(int u)
    {
        if(res[u])
        {
            reser(ch[u][0]);
            reser(ch[u][1]);
            res[u] = 0;
        }
    }
    int st[N],tl;
    void down(int x)
    {
        st[tl=1]=x;
        while(!isroot(x))x=fa[x],st[++tl] = x;
        while(tl)pushdown(st[tl]),tl--;
    }
    void rotate(int x)
    {
        int y = fa[x],z = fa[y],k = (ch[y][1]==x);
        if(!isroot(y))ch[z][ch[z][1]==y] = x;
        fa[x] = z;
        ch[y][k] = ch[x][!k] , fa[ch[x][!k]] = y;
        ch[x][!k] = y,fa[y] = x;
        update(y),update(x);
    }
    void splay(int x)
    {
        down(x);
        while(!isroot(x))
        {
            int y = fa[x],z = fa[y];
            if(!isroot(y))
                (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
    }
    void access(int x)
    {
        int y = 0;
        while(x)
        {
            splay(x);
            ch[x][1] = y;
            update(x);
            y = x,x = fa[x];
        }
    }
    void mtr(int x)
    {
        access(x);
        splay(x);
        reser(x);
    }
    void link(int x,int y)
    {
        mtr(x);
        fa[x] = y;
    }
    void cut(int x,int y)
    {
        mtr(x);
        access(y);
        splay(y);
        ch[y][0] = fa[x] = 0;
        update(y);
    }
    void Magic(int x)
    {
        splay(x);
        update(x);
    }
    int findrt(int x)
    {
        access(x);
        splay(x);
        while(ch[x][0])x=ch[x][0];
        return x;
    }
    void query(db k,int x,int y)
    {
        mtr(x);
        access(y);
        splay(y);
        db ans = 0.0,D = k,A = 1.0;
        for(int i=0;i<=15;i++,A*=D)
        {
            ans += A*v[y][i]/dv[i];
        }
        printf("%.8e\n",ans);
    }
}tr;
int main()
{
    n = rd(),m = rd();
    scanf("%s",typ+1);
    dv[0]=1.0;
    for(int i=1;i<=15;i++)
        dv[i] = dv[i-1]*(db)i;
    for(int i=1;i<=n;i++)
    {
        f[i] = rd();scanf("%lf%lf",&a[i],&b[i]);
    }
    for(int x,y,i=1;i<=m;i++)
    {
        scanf("%s",typ+1);
        x = rd(),y = rd();
        if(typ[1]=='a')tr.link(x+1,y+1);
        if(typ[1]=='d')tr.cut(x+1,y+1);
        if(typ[1]=='m')
        {
            f[x+1]=y;
            scanf("%lf%lf",&a[x+1],&b[x+1]);
            tr.Magic(x+1);
        }
        if(typ[1]=='t')
        {
            scanf("%lf",&a[0]);
            if(tr.findrt(x+1)!=tr.findrt(y+1))
            {
                puts("unreachable");
            }else tr.query(a[0],x+1,y+1);
        }
    }
    return 0;
}

 

posted @ 2018-12-24 13:11  LiGuanlin  阅读(177)  评论(0编辑  收藏  举报