zoukankan      html  css  js  c++  java
  • bzoj 3779 重组病毒

    sol:

    题面看吐了,实际上操作就是

    1.access

    2.makeroot

    3.查询一个点到根上有多少虚边

    1. 和 2. 可以 access ,每次断掉的轻边子树 -1,新连的轻边子树 +1 ,用线段树维护一下子树即可,类似树剖套线段树的方法换根

    顺便复习一下换根

    1.如果当前点在根的子树里,直接加

    2.如果当前点就是根,整棵树加

    3.如果根在当前点的子树里,从根爬到 x 下面的一个儿子 p ,修改除 p 子树外所有点

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 100010; 
    int n,m,rt;
    int first[maxn],to[maxn << 1],nx[maxn << 1],cnt;
    inline void add(int u,int v)
    {
        to[++cnt] = v;
        nx[cnt] = first[u];
        first[u] = cnt;
    }
    inline void ins(int u,int v){add(u,v);add(v,u);}
    int par[maxn][24],ind[maxn],oud[maxn],size[maxn],dep[maxn],reh[maxn],dfn;
    inline void dfs(int x)
    {
        size[x] = 1;ind[x] = ++dfn;reh[dfn] = dep[x];
        for(int i=1;i<=23;i++)par[x][i] = par[par[x][i - 1]][i - 1];
        for(int i=first[x];i;i=nx[i])
        {
            if(to[i] == par[x][0])continue;
            par[to[i]][0] = x;
            dep[to[i]] = dep[x] + 1;
            dfs(to[i]);size[x] += size[to[i]];
        }oud[x] = dfn;
    }
    LL seg[maxn << 2],tag[maxn << 2];
    inline void pushup(int x){seg[x] = seg[x << 1] + seg[x << 1 | 1];}
    inline void pushdown(int x,int l,int r)
    {
        if(tag[x])
        {
            int mid = (l + r) >> 1;
            tag[x << 1] += tag[x];tag[x << 1 | 1] += tag[x];
            seg[x << 1] += (mid - l + 1) * tag[x];seg[x << 1 | 1] += (r - mid) * tag[x];
            tag[x] = 0;
        }
    }
    inline void build(int x,int l,int r)
    {
        if(l == r)
        {
            seg[x] = reh[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(x << 1,l,mid);build(x << 1 | 1,mid + 1,r);
        pushup(x);
    }
    inline void update(int x,int l,int r,int L,int R,LL v)
    {
        if(L <= l && r <= R)
        {
            tag[x] += v;
            seg[x] += (r - l + 1) * v;
            return;
        }
        pushdown(x,l,r);
        int mid = (l + r) >> 1;
        if(L <= mid)update(x << 1,l,mid,L,R,v);
        if(R > mid)update(x << 1 | 1,mid + 1,r,L,R,v);
        pushup(x);
    }
    inline LL query(int x,int l,int r,int L,int R)
    {
        if(L <= l && r <= R)return seg[x];
        int mid = (l + r) >> 1;LL ans = 0;
        pushdown(x,l,r);
        if(L <= mid)ans += query(x << 1,l,mid,L,R);
        if(R > mid)ans += query(x << 1 | 1,mid + 1,r,L,R);
        return ans;
    }
    inline int isin(int x,int rt){return ind[rt] >= ind[x] && ind[rt] <= oud[x];}
    inline int getson(int x,int rt)
    {
        int t = dep[x] - dep[rt] - 1;
        for(int i=23;~i;i--)if(t & (1 << i))x = par[x][i];
        return x;
    }
    inline void Modify(int x,LL v)
    {
        if(x == rt)update(1,1,n,1,n,v);
        else if(isin(x,rt))
        {
            int vn = getson(rt,x);
            if(ind[vn] > 1)update(1,1,n,1,ind[vn] - 1,v);
            if(oud[vn] < n)update(1,1,n,oud[vn] + 1,n,v);
        }
        else update(1,1,n,ind[x],oud[x],v);
    }
    inline double Query(int x)
    {
        if(x == rt)return 1.0 * query(1,1,n,1,n) / n;
        else if(isin(x,rt))
        {
            double ans = 0;
            int vn = getson(rt,x);
            if(ind[vn] > 1)ans += query(1,1,n,1,ind[vn] - 1);
            if(oud[vn] < n)ans += query(1,1,n,oud[vn] + 1,n);
            return ans / (n - size[vn]);
        }
        else return (1.0 * query(1,1,n,ind[x],oud[x]) / size[x]);
    }
    #define ls ch[x][0]
    #define rs ch[x][1]
    int fa[maxn],ch[maxn][2],rev[maxn],st[maxn],top;
    inline int isroot(int x){return ch[fa[x]][1] != x && ch[fa[x]][0] != x;}
    inline void pushdown(int x)
    {
        if(rev[x])
        {
            swap(ls,rs);
            rev[ls] ^= 1;
            rev[rs] ^= 1;
            rev[x] ^= 1;
        }
    }
    inline void rotate(int x)
    {
        int y = fa[x],z = fa[y];
        int l = (ch[y][1] == x),r = l ^ 1;
        if(!isroot(y))ch[z][ch[z][1] == y] = x;
        fa[x] = z;fa[ch[x][r]] = y;fa[y] = x;
        ch[y][l] = ch[x][r];ch[x][r] = y;
    }
    inline void splay(int x)
    {
        st[top = 1] = x;
        for(int i=x;!isroot(i);i=fa[i])st[++top] = fa[i];
        for(int i=top;i;i--)pushdown(st[i]);
        while(!isroot(x))
        {
            int y = fa[x],z = fa[y];
            if(!isroot(y))
            {
                if(ch[z][0] == y ^ ch[y][0] == x)rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    inline int fd(int x)
    {
        pushdown(x);
        while(ls)x = ls,pushdown(x);
        return x;
    }
    inline void access(int x)
    {
        for(int y=0;x;rs=y,y=x,x=fa[x])
        {
            splay(x);
            int tmp = fd(rs);if(rs) Modify(tmp,1);
            tmp = fd(y);if(y) Modify(tmp,-1);
        }
    }
    inline void makeroot(int x)
    {
        access(x);
        splay(x);
        rev[x] ^= 1;
        rt = x;
    }
    int main()
    {
        //freopen("20.in","r",stdin);
        //freopen("gen.out","w",stdout);
        n = read(),m = read();rt = 1;
        for(int i=2;i<=n;i++)ins(read(),read());
        dep[1] = 1;dfs(1);
        build(1,1,n);
        for(int i=1;i<=n;i++)fa[i] = par[i][0];
        char opt[50];
        while(m--)
        {
            scanf("%s",opt + 1);int x = read();
            if(opt[3] == 'L')access(x);
            else if(opt[3] == 'C')makeroot(x);
            else printf("%.10lf
    ",Query(x));
        }
    }
    View Code
  • 相关阅读:
    react native的注释
    p标签在div中垂直居中,并且div高度随着p标签文字内容的变化而变化
    express框架搭建服务端
    react native项目的创建和运行
    ES6通过使用babel兼容到ie9
    react父传子
    经典排序之 归并排序
    经典排序之 冒泡排序
    C++基础题
    关于虚函数的应用(10个例子)
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10250140.html
Copyright © 2011-2022 走看看