BZOJ 5020 [LCT][数学]

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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值