• BZOJ5020 THUWC2017在美妙的数学王国中畅游(LCT)


      明摆着的LCT,问题在于如何维护答案。首先注意到给出的泰勒展开式,并且所给函数求导非常方便,肯定要用上这玩意。容易想到展开好多次达到精度要求后忽略余项。因为x∈[0,1]而精度又与|x-x0|有关,当然是维护x=0.5时的各种东西,粗略算下大概到第13项就可以了。具体要维护的东西当然是对于x的不同次数分别维护一个和。注意编号从0开始。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 100010
    #define lson tree[k].ch[0]
    #define rson tree[k].ch[1]
    #define lself tree[tree[k].fa].ch[0]
    #define rself tree[tree[k].fa].ch[1]
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,fac[14];
    struct data{int ch[2],fa,rev,op;double a,b,ans[14],f[14];
    }tree[N];
    double calc(int op,int k,double x,double a,double b)
    {
        if (op==1) return ((k&3)<2?1:-1)*pow(a,k)*(k&1?cos(a*x+b):sin(a*x+b));
        if (op==2) return pow(a,k)*exp(a*x+b);
        if (op==3)
        {
            if (k==0) return a*x+b;
            if (k==1) return a;
            return 0;
        }
    }
    void up(int k){for (int i=0;i<13;i++) tree[k].ans[i]=tree[lson].ans[i]+tree[rson].ans[i]+tree[k].f[i];}
    void newpoint(int x)
    {
        for (int i=0;i<13;i++) tree[x].f[i]=0;
        for (int i=0;i<13;i++)
        {
            double t=calc(tree[x].op,i,0.5,tree[x].a,tree[x].b);double t2=1;
            for (int j=i;~j;j--) tree[x].f[j]+=t2*t/fac[j]/fac[i-j],t2/=-2;
        }
        up(x);
    }
    void rev(int k){if (k) swap(lson,rson),tree[k].rev^=1;}
    void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;}
    int whichson(int k){return rself==k;}
    bool isroot(int k){return lself!=k&&rself!=k;}
    void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
    void move(int k)
    {
        int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
        if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
        tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa;
        tree[k].ch[!p]=fa,tree[fa].fa=k;
        up(fa),up(k);
    }
    void splay(int k)
    {
        push(k);
        while (!isroot(k))
        {
            int fa=tree[k].fa;
            if (!isroot(fa))
                if (whichson(k)^whichson(fa)) move(k);
                else move(fa);
            move(k);
        }
    }
    void access(int k){for (int t=0;k;t=k,k=tree[k].fa) splay(k),tree[k].ch[1]=t,up(k);}
    void makeroot(int k){access(k),splay(k),rev(k);}
    int findroot(int k){access(k),splay(k);for (;lson;k=lson) down(k);splay(k);return k;}
    void link(int x,int y){makeroot(x),tree[x].fa=y;}
    void cut(int x,int y){makeroot(x),access(y),splay(y);tree[x].fa=tree[y].ch[0]=0,up(y);}
    void modify(int x,int op,double a,double b){access(x),splay(x);tree[x].op=op,tree[x].a=a,tree[x].b=b;newpoint(x);}
    double query(int u,int v,double x)
    {
        makeroot(u),access(v),splay(v);
        double s=0,t=1;
        for (int i=0;i<13;i++)
        {
            s+=t*tree[v].ans[i];
            t*=x;
        }
        return s;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj5020.in","r",stdin);
        freopen("bzoj5020.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        fac[0]=1;for (int i=1;i<13;i++) fac[i]=fac[i-1]*i;
        n=read(),m=read();read();
        for (int i=1;i<=n;i++) tree[i].op=read(),scanf("%lf %lf",&tree[i].a,&tree[i].b),newpoint(i);
        while (m--)
        {
            char c=getc();
            switch (c)
            {
                case 'a':{link(read()+1,read()+1);break;}
                case 'd':{cut(read()+1,read()+1);break;}
                case 'm':
                {
                    int x=read()+1,op=read();double a,b;scanf("%lf %lf",&a,&b);
                    modify(x,op,a,b);
                    break;
                }
                case 't':
                {
                    int u=read()+1,v=read()+1;double x;scanf("%lf",&x);
                    if (findroot(u)!=findroot(v)) printf("unreachable
    ");
                    else printf("%.10f
    ",query(u,v,x));
                    break;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    LeetCode:230. 二叉搜索树中第K小的元素
    LeetCode:229. 求众数 II
    LeetCode:228. 汇总区间
    LeetCode:225. 用队列实现栈
    LeetCode:209. 长度最小的子数组
    LeetCode:208. 实现 Trie (前缀树)
    疯狂的订餐系统-软件需求分析挑战之旅 【转】
    产品需求文档(PRD)的写作 【转】
    软件需求文档标准格式
    通过实例编写开发规范文档 【转】
  • 原文地址:https://www.cnblogs.com/Gloid/p/10085930.html
Copyright © 2020-2023  润新知