• 题解 P4546/LOJ 2289【[THUWC2017]在美妙的数学王国中畅游】


    简化题面

    维护四种操作和一颗树

    (1)、断开(u)(v)之间的边
    (2)、在(u)(v)之间连一条边
    (3)、讲节点(c)更换为(i)种函数,且系数和常数项为(a)(b)
    (4)、查询(u)(v)路径上所有点上函数带入等于(x)时的函数值之和

    (nle 10^5)(mle 2 imes 10^5)

    解题思路

    首先(1,2)号操作告诉我们这题肯定要用(mathcal{LCT})来做,但是考虑怎么维护函数和函数值,根据小绿本高等数学上有个叫泰勒展开的玩意,我们对于每个节点维护其函数的泰勒展开来代表其近似值,因为三个函数(x)的幂数都很小因此我们维护大概展开(10)次的函数即可,最后查询的时候直接代入即可,具体看代码。

    (mathcal{Code})

    // Author: Ame__
    #include<bits/stdc++.h>
    #define _ 0
    //#define AME__
    #define AME__DEBUG
    #define bomb exit(0)
    #define LOG(FMT...) fprintf(stderr , FMT)
    #define TOWA(FMT...) fprintf(stdout , FMT)
    using namespace std;
    /*Grievous Lady*/
        
    typedef int32_t i32;
    typedef int64_t i64;
    typedef double qwq
    
    const int BUF_SIZE = 1 << 12;
    char buf[BUF_SIZE] , *buf_s = buf , *buf_t = buf + 1;
        
    #define PTR_NEXT() 
    { 
        buf_s ++; 
        if(buf_s == buf_t) 
        { 
            buf_s = buf; 
            buf_t = buf + fread(buf , 1 , BUF_SIZE , stdin); 
        } 
    }
        
    #define mians(_s_) 
    { 
        while(!isgraph(*buf_s)) PTR_NEXT();
        char register *_ptr_ = (_s_); 
        while(isgraph(*buf_s) || *buf_s == '-') 
        { 
            *(_ptr_ ++) = *buf_s; 
            PTR_NEXT(); 
        } 
        (*_ptr_) = ''; 
    }
        
    template <typename _n_> void mian(_n_ & _x_){
        char buf_s; while(buf_s != '-' && !isdigit(buf_s)) buf_s = getchar();
        bool register _nega_ = false; if(buf_s == '-'){ _nega_ = true; buf_s = getchar(); }
        _x_ = 0; while(isdigit(buf_s)){  _x_ = _x_ * 10 + buf_s - '0'; buf_s = getchar(); } if(_nega_) _x_ = -_x_;
    }
        
    const i32 kato = 2e5 + 10;
    
    template <typename _n_> bool cmax(_n_ &a , const _n_ &b){ return a < b ? a = b , 1 : 0; }
    template <typename _n_> bool cmin(_n_ &a , const _n_ &b){ return a > b ? a = b , 1 : 0; }
        
    i32 n , m , op , x , y;
    qwq a , b;
    qwq qaq[2] , opt[20];
    
    namespace towa{
        struct Tylar{
            qwq a[12];
            void clear(){ memset(a , 0 , sizeof a); }
            Tylar(){ clear(); }
            Tylar(i32 opt , qwq x , qwq y){
            	y += x * 0.5;
                if(opt == 1){
                    qwq res = 1 , f = sin(y) , g = cos(y);
                    for(int i = 1;i <= 11;i ++ , res = res * x , swap(f = -f , g)) this -> a[i] = res * f;
                }else if(opt == 2){
                    qwq res = exp(y);
                    for(int i = 1;i <= 11;i ++ , res *= x) this -> a[i] = res;
                }else *this = Tylar() , this -> a[1] = y , this -> a[2] = x;
            }
            friend Tylar operator + (const Tylar &a , const Tylar &b){
                Tylar c;
                for(i32 i = 1;i <= 11;i ++) c.a[i] = a.a[i] + b.a[i];
                return c;
            }
            inline qwq get_ans(qwq x){
                qwq res = 0; x -= 0.5;
                for(i32 i = 11 ; i ; i --) res = this -> a[i] + res * x / i;
                return res;
            }
        };
    
        struct node{
            node *ch[2] , *fa;
            static queue<node*> q;
            i32 rev;
            Tylar val , tot;
            node(node *fa = 0x0 , i32 rev = 0): fa(fa) , rev(rev){
                ch[0] = ch[1] = 0x0;
            }
            inline bool ntr(){
                return fa && (fa -> ch[0] == this || fa -> ch[1] == this);
            }
            inline bool isr(){
                return this == fa -> ch[1];
            }
            inline void Modify_rev(){
                rev ^= 1; swap(ch[0] , ch[1]);
            }
            inline void up(){
                tot = this -> val;
                if(ch[0]) this -> tot = this -> tot + ch[0] -> tot;
                if(ch[1]) this -> tot = this -> tot + ch[1] -> tot;
            }
            inline void down(){
                if(rev){
                    if(ch[0]) ch[0] -> Modify_rev(); if(ch[1]) ch[1] -> Modify_rev();
                    rev = 0;
                }
            }
            void *operator new(size_t){
                static node *S = 0x0 , *T = 0x0; node *tmp;
                return q.empty() ? (S == T && (T = (S = new node[1024]) + 1024 , S == T) ? 0x0 : S ++) : (tmp = q.front() , q.pop() , tmp);
            }
            void operator delete(void *qaq){ q.push(static_cast<node*>(qaq)); }
        }pool[kato];
    
        queue<node*> node::q;
    
        inline void split(node *x){
            node *y = x -> fa , *z = y -> fa;
            y -> down() , x -> down();
            int k = x -> isr(); node *w = x -> ch[!k];
            if(y -> ntr()) z -> ch[y -> isr()] = x;
            x -> ch[!k] = y , y -> ch[k] = w;
            y -> fa = x , x -> fa = z;
            if(w) w -> fa = y;
            y -> up() , x -> up();
        }
    
        inline void splay(node *o){
            static node *tree[kato]; int top = 0;
            tree[top = 1] = o;
            while(tree[top] -> ntr()) tree[top + 1] = tree[top] -> fa , top ++;
            while(top) tree[top --] -> down();
            while(o -> ntr()){
                if(o -> fa -> ntr()) split(o -> isr() ^ o -> fa -> isr() ? o : o -> fa);
                split(o);
            }
        }
    
        inline void access(node *x){
            for(node *y = 0x0 ; x ; x = (y = x) -> fa){
                splay(x) , x -> ch[1] = y , x -> up();
            }
        }
    
        inline void Move_to_root(node *x){
            access(x) , splay(x) , x -> Modify_rev();
        }
    
        inline node *find_root(node *x){
            access(x) , splay(x);
            while(x -> down() , x -> ch[0]) x = x -> ch[0];
            return splay(x) , x;
        }
    
        inline void link(node *x , node *y){
            if(find_root(x) == find_root(y)) return;
            Move_to_root(x); x -> fa = y;
        }
    
        inline void cut(node *x , node *y){
            Move_to_root(x); access(y); splay(y);
            y -> ch[0] = x -> fa = 0x0 , y -> up();
        }
    
        inline void change(int id , int tp , qwq a , qwq b){
            node *o = pool + id;
            splay(o);
            o -> val = Tylar(tp , a , b);
            o -> up();
        }
    
        inline Tylar query(node *x , node *y){ 
            Move_to_root(x) , access(y) , splay(y);
            return y -> tot;
        }
    
        inline void link(int x , int y){
            link(pool + x , pool + y);
        }
    
        inline void cut(int x , int y){
            cut(pool + x , pool + y);
        }
    
        inline void get_ans(int x , int y , qwq z){
            if(find_root(pool + x) == find_root(pool + y)) TOWA("%.10f
    " , query(pool + x , pool + y).get_ans(z));
            else TOWA("unreachable
    ");
        }
    }
    
    inline int Ame_(){
    #ifdef AME__
        freopen("b1.in" , "r" , stdin); freopen("1.out" , "w" , stdout); int nol_cl = clock();
    #endif
        mian(n) , mian(m); scanf("%s" , qaq);
        for(int i = 0;i < n;i ++) mian(op) , scanf("%lf%lf" , &a , &b) , towa::change(i , op , a , b);
        for(; m --> 0 ;){
            scanf("%s" , opt);
            if(opt[0] == 'a') mian(x) , mian(y) , towa::link(x , y);
            if(opt[0] == 'm') mian(x) , mian(y) , scanf("%lf%lf" , &a , &b) , towa::change(x , y , a , b);
            if(opt[0] == 'd') mian(x) , mian(y) , towa::cut(x , y);
            if(opt[0] == 't') mian(x) , mian(y) , scanf("%lf" , &a) , towa::get_ans(x , y , a);
        }
    #ifdef AME__TIME
        LOG("Time: %dms
    ", int((clock() - nol_cl) / (qwq)CLOCKS_PER_SEC * 1000));
    #endif
        return ~~(0^_^0); /*さようならプログラム*/
    }
        
    int Ame__ = Ame_();
        
    int main(){;}
    
    呐,这份感情,什么时候可以传达呢
  • 相关阅读:
    MianShiTi
    C#多线程解决界面卡死问题的完美解决方案
    C#中的WebBrowser控件的使用
    解决Linq第一次调用存储过程时速度慢的问题
    AX 的 NumberSequences
    Ax 从一个form关闭另外一个form,AX全局变量
    查询数据库后台Block 的Sql存储过程
    Dynamic AX 4.0 用户组权限SecurityKey
    20160408 从软件工程的3大文档开始说起
    获取AX的窗口所有控件的lableID及内容
  • 原文地址:https://www.cnblogs.com/Ame-sora/p/14423204.html
Copyright © 2020-2023  润新知