zoukankan      html  css  js  c++  java
  • bzoj 5020(洛谷4546) [THUWC 2017]在美妙的数学王国中畅游——LCT+泰勒展开

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5020

       https://www.luogu.org/problemnew/show/P4546

    如果保证 x=1 ,则可以用 LCT 维护每个点的函数值。不然的话就用 LCT 拿出那条链,dfs 一下 splay 现算。可以得 60 分。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define db double
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    const int N=1e5+5;
    int n,m,fa[N],c[N][2],sta[N],top; db sm[N],vl[N]; bool fx,rev[N];
    struct Node{
      int f;db a,b;
      db cal(db x)
      {
        if(f==1)return sin(a*x+b);
        if(f==2)return exp(a*x+b);
        if(f==3)return a*x+b;
      }
    }a[N];
    bool isroot(int cr){return c[fa[cr]][0]!=cr&&c[fa[cr]][1]!=cr;}
    void pshp(int cr){sm[cr]=sm[c[cr][0]]+sm[c[cr][1]]+vl[cr];}
    void Rev(int cr){if(rev[cr]){rev[cr]=0;rev[c[cr][0]]^=1;rev[c[cr][1]]^=1;swap(c[cr][0],c[cr][1]);}}
    void rotate(int x)
    {
      int y=fa[x],z=fa[y],d=(x==c[y][1]);
      if(!isroot(y))c[z][y==c[z][1]]=x;//!isroot(y) not !isroot(z) !!
      fa[x]=z;
      fa[y]=x; fa[c[x][!d]]=y;
      c[y][d]=c[x][!d]; c[x][!d]=y;
      if(fx)pshp(y),pshp(x);
    }
    void splay(int x)
    {
      sta[top=1]=x;
      for(int cr=x;!isroot(cr);cr=fa[cr])sta[++top]=fa[cr];
      for(int i=top;i;i--)Rev(sta[i]);
      int y,z;
      while(!isroot(x))
        {
          y=fa[x];z=fa[y];
          if(!isroot(y))
        ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y);
          rotate(x);
        }
    }
    void access(int cr)
    {
      for(int t=0;cr;splay(cr),c[cr][1]=t,pshp(cr),t=cr,cr=fa[cr]);//pshp()!!
    }
    void mkrt(int cr)
    {
      access(cr);splay(cr);rev[cr]^=1;
    }
    void link(int x,int y)
    {
      mkrt(x);fa[x]=y;
    }
    void cut(int x,int y)
    {
      mkrt(x);access(y);splay(y);
      fa[x]=c[y][0]=0;if(fx)sm[y]-=vl[x];
    }
    void mdfy(int cr,int f,db a1,db b1)
    {
      if(fx)splay(cr),sm[cr]-=vl[cr];
      a[cr].f=f;a[cr].a=a1;a[cr].b=b1;
      if(fx)vl[cr]=a[cr].cal(1),sm[cr]+=vl[cr];
    }
    int fnd(int cr)//root of real tree
    {
      while(!isroot(cr))cr=fa[cr];return cr;
    }
    db dfs(int cr,db x)
    {
      db ret=a[cr].cal(x);
      if(c[cr][0])ret+=dfs(c[cr][0],x);
      if(c[cr][1])ret+=dfs(c[cr][1],x);
      return ret;
    }
    void print(db x)
    {
      bool fx=0;int t=0;
      if(x<1){fx=1;while(x<1)x*=10,t++;}
      if(x>=10){while(x>=10)x/=10,t++;}
      printf("%.8fe%c%03d
    ",x,fx?'-':'+',t);
    }
    int main()
    {
      n=rdn();m=rdn();char ch[15];scanf("%s",ch);
      if(ch[1]=='0')fx=1;
      for(int i=1;i<=n;i++)
        {
          a[i].f=rdn();scanf("%lf%lf",&a[i].a,&a[i].b);
          if(fx)vl[i]=sm[i]=a[i].cal(1);
        }
      int u,v;db a,b,x;
      while(m--)
        {
          scanf("%s",ch);
          if(ch[0]=='a'){u=rdn()+1;v=rdn()+1;link(u,v);}
          if(ch[0]=='d'){u=rdn()+1;v=rdn()+1;cut(u,v);}
          if(ch[0]=='m'){u=rdn()+1;v=rdn();scanf("%lf%lf",&a,&b);mdfy(u,v,a,b);}
          if(ch[0]=='t')
        {
          u=rdn()+1;v=rdn()+1;scanf("%lf",&x);
          mkrt(u);access(v);splay(v);
          if(fnd(u)!=v)puts("unreachable");
          else print(fx?sm[v]:dfs(v,x));
        }
        }
      return 0;
    }
    View Code

    关于本题的求导和泰勒展开可以看这个:https://www.cnblogs.com/zhoushuyu/p/8148732.html

    似乎还可以麦克劳林展开:https://www.cnblogs.com/Troywar/p/8982707.html

    似乎展开成 12 项的多项式就差不多了,然后可以用 LCT 维护 12 项的系数和,算的时候乘上 xk 再除以阶乘就行。

    那个 x0 好像取 0 就行了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define db double
    #define ls c[cr][0]
    #define rs c[cr][1]
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    using namespace std;
    const int N=1e5+5,M=12;
    int n,fa[N],c[N][2],sta[N],top; bool rev[N]; db sm[N][M+5],vl[N][M+5],jc[N];
    struct Node{
      int f;db a,b;
      Node(int f=0,db a=0,db b=0):f(f),a(a),b(b) {}
      void cz(int cr)
      {
        if(f==1)
          {
        db p[5],lja=1;
        p[0]=sin(b);p[1]=cos(b);p[2]=-p[0];p[3]=-p[1];
        for(int i=0;i<M;i+=4)
          for(int j=0;j<4;j++,lja*=a)sm[cr][i+j]=vl[cr][i+j]=p[j]*lja;
          }
        if(f==2)
          {
        db ml=exp(b),lja=1;
        for(int i=0;i<M;i++,lja*=a)sm[cr][i]=vl[cr][i]=ml*lja;
          }
        if(f==3)
          {
        sm[cr][0]=vl[cr][0]=b; sm[cr][1]=vl[cr][1]=a;
        for(int i=2;i<M;i++)sm[cr][i]=vl[cr][i]=0;
          }
      }
    }w[N];
    bool isrt(int cr){return c[fa[cr]][0]!=cr&&c[fa[cr]][1]!=cr;}
    void pshp(int cr)
    {
      for(int i=0;i<M;i++)sm[cr][i]=sm[ls][i]+sm[rs][i]+vl[cr][i];
    }
    void Rev(int cr){if(rev[cr]){rev[cr]=0;rev[ls]^=1;rev[rs]^=1;swap(ls,rs);}}
    void rotate(int x)
    {
      int y=fa[x],z=fa[y],d=(x==c[y][1]);
      if(!isrt(y))c[z][y==c[z][1]]=x;
      fa[x]=z;
      fa[y]=x; fa[c[x][!d]]=y;
      c[y][d]=c[x][!d]; c[x][!d]=y;
      pshp(y);pshp(x);
    }
    void splay(int x)
    {
      sta[top=1]=x;
      for(int cr=x;!isrt(cr);cr=fa[cr])sta[++top]=fa[cr];
      for(int i=top;i;i--)Rev(sta[i]);
      int y,z;
      while(!isrt(x))
        {
          y=fa[x];z=fa[y];
          if(!isrt(y))
        ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y);
          rotate(x);
        }
    }
    void access(int cr)
    {
      for(int t=0;cr;splay(cr),rs=t,pshp(cr),t=cr,cr=fa[cr]);//pshp()!!!
    }
    void mkrt(int cr)
    {
      access(cr);splay(cr);rev[cr]^=1;
    }
    void link(int x,int y)
    {
      mkrt(x);fa[x]=y;
    }
    void cut(int x,int y)
    {
      mkrt(x);access(y);splay(y);
      fa[x]=c[y][0]=0;pshp(y);
    }
    void mdfy(int cr,int f,db a,db b)
    {
      splay(cr);
      w[cr]=Node(f,a,b);w[cr].cz(cr);
    }
    db cal(int cr,db x)
    {
      db ret=0,ml=1;
      for(int i=0;i<M;i++,ml*=x)
        ret+=sm[cr][i]*ml/jc[i];
      return ret;
    }
    int fnd(int cr)
    {
      while(!isrt(cr))cr=fa[cr];return cr;
    }
    void print(db x)
    {
      bool fx=0;int t=0;
      if(x<1){fx=1;while(x<1)x*=10,t++;}
      if(x>=10){while(x>=10)x/=10,t++;}
      printf("%.8fe%c%03d
    ",x,fx?'-':'+',t);
    }
    int main()
    {
      jc[0]=1;for(int i=1;i<M;i++)jc[i]=jc[i-1]*i;
      n=rdn();int m=rdn();char ch[15];scanf("%s",ch);
      for(int i=1;i<=n;i++)
        w[i].f=rdn(),scanf("%lf%lf",&w[i].a,&w[i].b),w[i].cz(i),pshp(i);//pshp for sm[]
      int u,v;db a,b;
      while(m--)
        {
          scanf("%s",ch);
          if(ch[0]=='a'){u=rdn()+1;v=rdn()+1;link(u,v);}
          if(ch[0]=='d'){u=rdn()+1;v=rdn()+1;cut(u,v);}
          if(ch[0]=='m'){u=rdn()+1;v=rdn();scanf("%lf%lf",&a,&b);mdfy(u,v,a,b);}
          if(ch[0]=='t')
        {
          u=rdn()+1;v=rdn()+1;scanf("%lf",&a);
          mkrt(u);access(v);splay(v);
          if(fnd(u)!=v)puts("unreachable");
          else print(cal(v,a));
        }
        }
      return 0;
    }
  • 相关阅读:
    mysql prepare语句使用
    mysql 存储过程中的declare 和 set @的两种变量的区别
    Redis命令总结
    系统架构师
    php 大数组的POST问题解决
    ubuntu设置系统时间与网络时间同步
    JAVA开发者最常去的20个英文网站
    文件上传之一句话木马原理及制作
    Postman怎么进行参数化
    单元测试、接口测试、功能测试的区别
  • 原文地址:https://www.cnblogs.com/Narh/p/10253975.html
Copyright © 2011-2022 走看看