zoukankan      html  css  js  c++  java
  • [2017/5/28]FJ四校联考

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    话说这一段时间算是过去了,好久好久之后终于又有联考了  没想到这次到我们学校出题,昨天才想起来,临时花一天赶了一套,我出了一个sbFFT,质量勉强吧。

    upd:代码已经更新

    A.种树

    有一棵二叉树,有点权,你要从节点1出发前往一个节点,如果路上的节点权值和他相等就结束,否则比他小向左,比他大向右,问能不能找到。

    需要支持多组询问,单点修改,子树反转

    n,m<=10^5

    #include<iostream>
    #include<cstdio>
    #define pa pair<int,int> 
    #define mp(x,y) make_pair(x,y)
    #define MN 100000
    #define INF 2000000000 
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    struct data{int lmn,lmx,rmn,rmx;
        friend data operator +(data a,data b)
        {
            data c;
            c.lmn=min(a.lmn,b.lmn);
            c.rmx=max(a.rmx,b.rmx);
            c.lmx=(a.lmx==INF)?b.lmx:(b.lmx==INF?a.lmx:max(a.lmx,b.lmx)); 
            c.rmn=(a.rmn==-INF)?b.rmn:(b.rmn==-INF?a.rmn:min(a.rmn,b.rmn));
            return c;
        }
        void rev()
        {
            swap(lmn,rmn);if(lmn==-INF) lmn=INF;if(rmn==INF) rmn=-INF;
            swap(lmx,rmx);if(rmx==INF) rmx=-INF;if(lmx==-INF)lmx=INF;
        }
    };
    struct Tree{int l,r,rev;data x;}T[MN*4+5];
    int l[MN+5],r[MN+5],num[MN+5],fa[MN+5],top[MN+5],n,m,w[MN+5],dn=0,nl[MN+5],nr[MN+5],size[MN+5];
    pa p[MN+5];
    
    void Dfs1(int x)
    {
        if(l[x]) Dfs1(l[x]),fa[l[x]]=x;
        if(r[x]) Dfs1(r[x]),fa[r[x]]=x;
        size[x]=size[l[x]]+size[r[x]]+1; 
    } 
    
    void Dfs2(int x,int tp)
    {
        if(!x) return;top[x]=tp;num[nl[x]=++dn]=x;
        if(size[l[x]]>size[r[x]]) Dfs2(l[x],tp),Dfs2(r[x],r[x]);
        else Dfs2(r[x],tp),Dfs2(l[x],l[x]);
        p[l[x]]=mp(1,w[x]);p[r[x]]=mp(2,w[x]);
        nr[x]=dn;
    }
    
    void build(int x,int l,int r)
    {
        if((T[x].l=l)==(T[x].r=r))
        {
            int now=num[l];
            if(p[now].first==1)
                T[x].x=(data){p[now].second,p[now].second,-INF,-INF};
            else 
                T[x].x=(data){INF,INF,p[now].second,p[now].second};
            return;
        }
        int mid=l+r>>1;
        build(x<<1,l,mid);build(x<<1|1,mid+1,r);
        T[x].x=T[x<<1].x+T[x<<1|1].x;
    }
    
    inline void Mark(int x)
    {
        T[x].rev^=1;
        T[x].x.rev();    
    }
    
    inline void pushdown(int x)
    {
        Mark(x<<1);Mark(x<<1|1);
        T[x].rev=0;
    }
    
    void Modify(int x,int v,pa k)
    {
        if(T[x].l==T[x].r)
        {
            if(k.first==1^T[x].rev)
                T[x].x=(data){k.second,k.second,-INF,-INF};
            else 
                T[x].x=(data){INF,INF,k.second,k.second};
            return;
        }
        if(T[x].rev) pushdown(x);
        int mid=(T[x].l+T[x].r)>>1;
        if(v<=mid) Modify(x<<1,v,k);
        else if(v>mid) Modify(x<<1|1,v,k);
        T[x].x=T[x<<1].x+T[x<<1|1].x;
    }
    
    void Reverse(int x,int l,int r)
    {
        if(T[x].l==l&&T[x].r==r){Mark(x);return;}
        int mid=(T[x].l+T[x].r)>>1;
        if(T[x].rev) pushdown(x);
        if(r<=mid) Reverse(x<<1,l,r);
        else if(l>mid) Reverse(x<<1|1,l,r);
        else Reverse(x<<1,l,mid),Reverse(x<<1|1,mid+1,r);
        T[x].x=T[x<<1].x+T[x<<1|1].x;
    }
    
    data Query(int x,int l,int r)
    {
        if(T[x].l==l&&T[x].r==r) return T[x].x;
        if(T[x].rev) pushdown(x);
        int mid=(T[x].l+T[x].r)>>1;
        if(r<=mid) return Query(x<<1,l,r);
        else if(l>mid) return Query(x<<1|1,l,r);
        else return Query(x<<1,l,mid)+Query(x<<1|1,mid+1,r); 
    }
    
    data Solve(int x)
    {
        data res=(data){INF,INF,-INF,-INF};
        for(;x;x=fa[top[x]]) res=res+Query(1,nl[top[x]],nl[x]);
        return res;
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;++i) w[i]=read(),l[i]=read(),r[i]=read();
        Dfs1(1);Dfs2(1,1);p[1]=mp(1,INF);build(1,1,n);
        for(int i=1;i<=m;++i)
        {
            int op=read(),x=read();
            if(op==1) 
            {
                int y=read();
                if(l[x]) Modify(1,nl[l[x]],mp(1,y));
                if(r[x]) Modify(1,nl[r[x]],mp(2,y));
                w[x]=y;    
            }
            if(op==2)
            {
                if(nl[x]!=nr[x])
                    Reverse(1,nl[x]+1,nr[x]);    
            }
            if(op==3)
            {
                data y=Solve(x);
                if(w[x]<y.lmn&&w[x]>y.rmx) puts("YES");
                else puts("NO");
            }
        }
        return 0;
    }

    把一条边看成一个限制条件,也就是大于或者小于某个值。那么树链剖分之后线段树维护就行了,维护区间小于限制的最大/最小值,大于限制的最大/最小值。

    子树反转可以打标记实现。复杂度nlog^2n

    代码貌似丢在学校了,端午过后补吧。

    B.mark

    C.秋之国的盛会

    给定两个长度为n的序列ai,bi,可以把a向后推动0到n次。给定c,m,推动k次的时候的费用是$sum{(frac{ai}{bi}-c*k-m)^2}$

    n<=10^5

    求最小费用

    把这个式子展开,很容易发现只要能快速求出不同推动状态下的$sum{frac{ai}{bi}}$和$sum{(frac{ai}{bi})^2}$即可。

    把ai数组倒过来并复制一遍,b数组变成1/bi,fft求卷积即可。另一项同理。

    复杂度nlogn

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define pi acos(-1)
    #define ld long double
    #define MN 262144
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int N,n,M;double cost;
    struct cp
    {
        ld r,u;
        cp ( double x = 0,double y = 0) :r(x) , u(y) {}
        cp operator + (const cp&y) { return cp(r+y.r,u+y.u);}
        cp operator - (const cp&y) { return cp(r-y.r,u-y.u);}
        cp operator * (const cp&y) { return cp(r*y.r-u*y.u,r*y.u+u*y.r);}        
        cp operator * (ld y){return cp(r*y,u*y);}
        cp operator / (ld y){return cp(r/y,u/y);}
    }A[MN+5],B[MN+5],C[MN+5],a[MN+5],b[MN+5],c[MN+5],w[2][MN+5];
    
    void fft(cp*x,int r)
    {
        for(int i=0,j=0;i<N;++i)
        {
            if(i>j) swap(x[i],x[j]);
            for(int l=N>>1;(j^=l)<l;l>>=1);    
        }
        for(int i=2;i<=N;i<<=1)for(int j=0;j<N;j+=i)for(int k=0;k<i>>1;++k)
        {
            cp t=x[j+k+(i>>1)]*w[r][N/i*k];
            x[j+k+(i>>1)]=x[j+k]-t;
            x[j+k]=x[j+k]+t;    
        }
        if(r)for(int i=0;i<N;++i) x[i]=x[i]/N;
    }
    
    int main()
    {
        freopen("party.in","r",stdin);
        freopen("party.out","w",stdout); 
        n=read();M=read();scanf("%lf",&cost);
        for(int i=n-1;~i;--i)  a[i].r=read(),A[i].r=a[i].r*a[i].r;
        for(int i=0;i<n;++i)  b[i].r=(ld)1/read(),B[i].r=b[i].r*b[i].r;
        for(int i=0;i<n;++i) a[i+n]=a[i],A[i+n]=A[i]; 
        for(N=1;N<=n<<1;N<<=1);
        w[0][0]=w[1][N]=cp(1,0);w[0][1]=w[1][N-1]=cp(cos(2*pi/N),sin(2*pi/N));
        for(int i=2;i<=N;++i) w[0][i]=w[1][N-i]=w[0][i-1]*w[0][1];
        fft(a,0);fft(b,0);fft(A,0);fft(B,0);
        for(int i=0;i<N;++i) c[i]=a[i]*b[i],C[i]=A[i]*B[i];
        fft(c,1);fft(C,1);
        ld ans=1e99;int mx=0;
        for(int i=n-1;i<n<<1;++i)
        {
            ld j=cost*(i-n+1);
            if(C[i].r-2*c[i].r*(j+M)+(ld)n*(j+M)*(j+M)<ans) mx=i-n+2;
            ans=min(ans,C[i].r-2*c[i].r*(j+M)+(ld)n*(j+M)*(j+M)); 
        }
        printf("%.10lf",(double)ans);
        return 0;
    }
  • 相关阅读:
    DM8168通过GPMC接口与FPGA高速数据通信实现
    2016年 我在浙大计算机学院在职研究生学习经历
    CCS Font 知识整理总结
    Hexo 博客部署到 GitHub
    树莓派配置 USB 无线网卡
    树莓派搭建 Hexo 博客(二)
    树莓派搭建 Hexo 博客(一)
    树莓派初次使用的基本配置.md
    语法测试cnblogs使用Markdown
    硬件工程师-面试笔记0305
  • 原文地址:https://www.cnblogs.com/FallDream/p/liankao528.html
Copyright © 2011-2022 走看看