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;
}
原文地址:https://www.cnblogs.com/Gloid/p/10085930.html