• bzoj 3779: 重组病毒【LCT+线段树维护dfs序】


    %.8lf会WA!!%.8lf会WA!!%.8lf会WA!!要%.10lf!!
    和4817有点像,但是更复杂。
    首先对于操作一“在编号为x的计算机中植入病毒的一个新变种,在植入一个新变种时,病毒会在局域网中搜索核心计算机的位置,并沿着网络中最短的路径感染过去”,长得是不是有点像LCT中的access操作?进而发现,如果把同一颜色的点连起来作为LCT中的重边的话,那么询问二就相当于问路径上的虚边有多少。
    假设没有换根操作,那么第二、三个操作是可以用树剖在线段树上维护的。 设每个点的权值val为这个点到根的路径上颜色个数,也就是虚边个数。那么考虑access操作的影响,对于他断开的重边,所在子树加一,对于他连上的重边,所在子树减一。直接在access过程中处理即可。
    那么现在考虑换根操作:
    首先出题人非常贴心的在换根操作后加了一个access,更加符合LCT的操作方式虽然不加应该就做不了了
    首先对1为根进行dfs,把dfs序摊到线段树上,在这个线段树上维护修改和查询。
    然后把平均数改成区间和,查完之后直接除即可(注意会爆int,注意精度问题)。
    那么对于当先换根换到的root和要查询的子树x,用dfs序判断有三种情况:

    • ( root=x ),相当于求全区间和,直接返回即可;
    • x在root的子树中,那么换根对它没有影响,直接当做没有换根来查询即可;
    • x不在root的子树中,那么答案为全区间和减去x下面root所在的子树的区间和。
    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=300005;
    int n,m,h[N],cnt,fa[N],de[N],fr[N],ed[N],id[N],dfn,rl[N],root=1,s[N],top;
    char c[10];
    struct qwe
    {
        int ne,to;
    }e[N<<1];
    struct xianduanshu
    {
        int l,r;
        long long sum,lz;
    }q[N<<2];
    struct pinghengshu
    {
        int f,c[2],tg;
    }t[N];
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p==-1)
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    void add(int u,int v)
    {
        cnt++;
        e[cnt].ne=h[u];
        e[cnt].to=v;
        h[u]=cnt;
    }
    void build(int ro,int l,int r)
    {
        q[ro].l=l,q[ro].r=r;
        if(l==r)
            return;
        int mid=(l+r)>>1;
        build(ro<<1,l,mid);
        build(ro<<1|1,mid+1,r);
    }
    void pd(int ro)
    {
        q[ro<<1].sum+=q[ro].lz*(q[ro<<1].r-q[ro<<1].l+1);
        q[ro<<1].lz+=q[ro].lz;
        q[ro<<1|1].sum+=q[ro].lz*(q[ro<<1|1].r-q[ro<<1|1].l+1);
        q[ro<<1|1].lz+=q[ro].lz;
        q[ro].lz=0;
    }
    void update(int ro,int l,int r,int v)
    {//cout<<l<<" "<<r<<" "<<v<<endl;
        if(l>r)
            return;
        if(q[ro].l==l&&q[ro].r==r)
        {
            q[ro].sum+=v*(q[ro].r-q[ro].l+1);
            q[ro].lz+=v;
            return;
        }
        if(q[ro].lz)
            pd(ro);
        int mid=(q[ro].l+q[ro].r)>>1;
        if(r<=mid)
            update(ro<<1,l,r,v);
        else if(l>mid)
            update(ro<<1|1,l,r,v);
        else
        {
            update(ro<<1,l,mid,v);
            update(ro<<1|1,mid+1,r,v);
        }
        q[ro].sum=q[ro<<1].sum+q[ro<<1|1].sum;
    }
    long long ques(int ro,int l,int r)
    {
        if(l>r)
            return 0;
        if(q[ro].l==l&&q[ro].r==r)
            return q[ro].sum;
        if(q[ro].lz)
            pd(ro);
        int mid=(q[ro].l+q[ro].r)>>1;
        if(r<=mid)
            return ques(ro<<1,l,r);
        else if(l>mid)
            return ques(ro<<1|1,l,r);
        else
            return ques(ro<<1,l,mid)+ques(ro<<1|1,mid+1,r);
    }
    void dfs(int u,int fat)
    {
        t[u].f=fa[u]=fat;
        de[u]=de[fat]+1;
        fr[u]=++dfn;
        update(1,fr[u],fr[u],de[u]);
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fat)
                dfs(e[i].to,u);
        ed[u]=dfn;
    }
    bool srt(int x)
    {
        return t[t[x].f].c[0]!=x&&t[t[x].f].c[1]!=x;
    }
    void pud(int x)
    {
        if(t[x].tg)
        {
            t[x].tg=0;
            t[t[x].c[0]].tg^=1;
            t[t[x].c[1]].tg^=1;
            swap(t[x].c[0],t[x].c[1]);
        }
    }
    void zhuan(int x)
    {
        int l,r,y=t[x].f,z=t[y].f;
        if(t[y].c[0]==x)
            l=0;
        else
            l=1;
        r=l^1;
        if(!srt(y))
        {
            if(t[z].c[0]==y)
                t[z].c[0]=x;
            else
                t[z].c[1]=x;
        }
        t[x].f=z;t[y].f=x;
        t[t[x].c[r]].f=y;
        t[y].c[l]=t[x].c[r];
        t[x].c[r]=y;
    }
    void splay(int x)
    {//cout<<"splay"<<x<<endl;
        top=0;
        s[++top]=x;
        for(int i=x;!srt(i);i=t[i].f)
            s[++top]=t[i].f;
        while(top)
            pud(s[top--]);
        while(!srt(x))
        {
            int y=t[x].f,z=t[y].f;
            if(!srt(y))
            {
                if((t[y].c[0]==x)^(t[z].c[0]==y))
                    zhuan(x);
                else
                    zhuan(y);
            }
            zhuan(x);
        }
    }
    int zhao(int x,int y)
    {
        for(int i=h[x];i;i=e[i].ne)
            if(e[i].to!=fa[x]&&fr[y]>=fr[e[i].to]&&ed[y]<=ed[e[i].to])
                return e[i].to;
        return 0;
    }
    void jia(int x,int w)
    {
        if(x==root)
            update(1,1,n,w);
        else if(fr[root]>=fr[x]&&ed[root]<=ed[x])
        {
            int zi=zhao(x,root);
            update(1,1,fr[zi]-1,w);
            update(1,ed[zi]+1,n,w);
        }
        else
            update(1,fr[x],ed[x],w);
    }
    int wk(int x)
    {
        pud(x);
        while(t[x].c[0])
            x=t[x].c[0],pud(x);
        return x;
    }
    void acc(int x)
    {
        for(int i=0;x;i=x,x=t[x].f)
        {
            splay(x);
            if(t[x].c[1])
                jia(wk(t[x].c[1]),1);
            t[x].c[1]=i;
            if(t[x].c[1])
                jia(wk(t[x].c[1]),-1);
        }
    }
    void mkrt(int x)
    {
        acc(x);
        splay(x);
        root=x;
        t[x].tg^=1;
    }
    double wen(int x)
    {//cout<<ques(1,id[x],id[x]+si[x]-1)<<endl;
        if(x==root)
            return (double)ques(1,1,n)/n;
        if(fr[root]>=fr[x]&&ed[root]<=ed[x])
        {
            int zi=zhao(x,root);
            return (double)(ques(1,1,fr[zi]-1)+ques(1,ed[zi]+1,n))/(n-(ed[zi]-fr[zi]+1));
        }
        return (double)ques(1,fr[x],ed[x])/(ed[x]-fr[x]+1);
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<n;i++)
        {
            int x=read(),y=read();
            add(x,y);add(y,x);
        }
        build(1,1,n);
        dfs(1,0);
        for(int i=2;i<=n;i++)
            t[i].f=fa[i];
        while(m--)
        {
            scanf("%s",c);
            if(c[2]=='L')
            {
                int x=read();
                acc(x);
            }
            else if(c[2]=='C')
            {
                int x=read();
                mkrt(x);
            }
            else
            {
                int x=read();
                printf("%.10lf
    ",wen(x));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    .NET拾忆:FileSystemWatcher 文件监控
    .NET拾忆:EventLog(Windows事件日志监控)
    MSSqlServer 主从同步复制原理(发布/订阅)
    MSSqlServer 发布/订阅配置(主从同步)
    Entity Framework Code First(Mysql)
    .Net拾忆:Asp.net请求管道
    http://blog.csdn.net/dianhuiren/article/details/7543886 该作者对操作系统底层研究较深
    page cache 与 page buffer 转
    linux free命令中buffer与cache的区别
    Nginx重写规则指南 转
  • 原文地址:https://www.cnblogs.com/lokiii/p/8244811.html
Copyright © 2020-2023  润新知