zoukankan      html  css  js  c++  java
  • bzoj3779: 重组病毒 link-cut-tree

    题目传送门

    这道题看了做了个神转换.....推荐个博客给各位大爷看看吧神犇传送门

    代码敲了半天....题目也读了半天 线段树维护的东西很容易和lct混在一起 调了调能过也是很开心啊 运气比较好吧233

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long 
    using namespace std;
    const int M=1<<17;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,m,rt;
    int next[M],sum,father[M],deep[M],first[M],second[M];
    struct Edge{int u,v,from;}e[2*M];
    void ins(int a,int b){sum++; e[sum].u=a; e[sum].v=b; e[sum].from=next[a]; next[a]=sum;}
    void insert(int a,int b){ins(a,b); ins(b,a);}
    struct node{int l,r; LL sum,tag;}tr[M*2];
    int c[M][2],fa[M],dfsum,rev[M];
    void build(int x,int l,int r){
        tr[x].l=l; tr[x].r=r;
        if(l==r) return ;
        int mid=(l+r)>>1;
        build(x<<1,l,mid); build(x<<1^1,mid+1,r);
    }
    void cal(int x,int w){tr[x].sum+=1LL*(tr[x].r-tr[x].l+1)*w;}
    void push_up(int x){tr[x].sum=tr[x<<1].sum+tr[x<<1^1].sum;}
    void push_down(int x){
        if(!tr[x].tag) return ;
        int w=tr[x].tag; tr[x].tag=0;
        int l=x<<1,r=x<<1^1;
        tr[l].tag+=w; cal(l,w);
        tr[r].tag+=w; cal(r,w);
    }
    void push_add(int x,int L,int R,int w){
        if(L>R) return ;
        if(L<=tr[x].l&&tr[x].r<=R){
            cal(x,w); 
            tr[x].tag+=1LL*w; return ;
        }
        if(tr[x].l==tr[x].r) return ;
        push_down(x);
        int mid=(tr[x].l+tr[x].r)>>1;
        if(L<=mid) push_add(x<<1,L,R,w);
        if(R>mid) push_add(x<<1^1,L,R,w);
        push_up(x);
    }
    LL push_ans(int x,int L,int R){
        if(L>R) return 0;
        if(L<=tr[x].l&&tr[x].r<=R) return tr[x].sum;
        //if(tr[x].l==tr[x].r) return 0;
        LL ans=0; push_down(x);
        int mid=(tr[x].l+tr[x].r)>>1;
        if(L<=mid) ans+=push_ans(x<<1,L,R);
        if(R>mid) ans+=push_ans(x<<1^1,L,R);
        return ans;
    }
    void dfs(int x,int old){
        father[x]=fa[x]=old;
        first[x]=++dfsum;
        deep[x]=deep[old]+1;
        push_add(1,first[x],first[x],deep[x]);
        for(int i=next[x];i;i=e[i].from) if(e[i].v!=old) dfs(e[i].v,x);
        second[x]=dfsum;
    }
    bool isrt(int x){return !x||(c[fa[x]][0]!=x&&c[fa[x]][1]!=x);}//0也算
    void down(int x){
        if(!rev[x]) return ;
        rev[x]=0;
        int l=c[x][0],r=c[x][1];
        if(l) swap(c[l][0],c[l][1]),rev[l]^=1;    
        if(r) swap(c[r][0],c[r][1]),rev[r]^=1;        
    }
    void rotate(int x){
        int y=fa[x],z=fa[y],l=0,r=1;
        if(c[y][1]==x) l=1,r=0;
        if(!isrt(y)) c[z][c[z][1]==y]=x;
        fa[y]=x; fa[x]=z; fa[c[x][r]]=y;
        c[y][l]=c[x][r]; c[x][r]=y;
    }
    int st[M],top;
    void splay(int x){
        st[++top]=x; for(int i=x;!isrt(i);i=fa[i])  st[++top]=fa[i];
        while(top) down(st[top--]);
        while(!isrt(x)){
            int y=fa[x],z=fa[y];
            if(!isrt(y)){
                if(c[z][0]==y^c[y][0]==x) rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    bool inson(int x,int y){return first[x]<=first[y]&&second[y]<=second[x];}
    int wson(int x,int y){
        for(int i=next[x];i;i=e[i].from) if(e[i].v!=father[x])
            if(first[e[i].v]<=first[y]&&second[y]<=second[e[i].v]) return e[i].v;
        return 0;
    }
    void add(int x,int w){
        if(x==rt) push_add(1,1,n,w);
        else if(inson(x,rt)){
            int p=wson(x,rt);
            push_add(1,1,first[p]-1,w);
            push_add(1,second[p]+1,n,w);
        }
        else push_add(1,first[x],second[x],w);
    }
    int find(int x){
        while(c[x][0]) down(x),x=c[x][0];
        return x;
    }
    void acs(int x){
        int y=0;
        while(x){
            splay(x);
            if(c[x][1]) add(find(c[x][1]),1);
            if(y) add(find(y),-1);
            c[x][1]=y; y=x; x=fa[x];
        }
    }
    double addup(int x){
        if(x==rt) return (double)push_ans(1,1,n)/n;
        if(inson(x,rt)){
            int p=wson(x,rt);
            return ((double)push_ans(1,1,first[p]-1)+(double)push_ans(1,second[p]+1,n))/(n-(second[p]-first[p]+1));
        }
        else return (double)push_ans(1,first[x],second[x])/(second[x]-first[x]+1);
    }
    void mrt(int x){splay(x); rt=x; swap(c[x][0],c[x][1]); rev[x]^=1;}
    int main()
    {
        int x,y;
        n=read(); m=read();
        for(int i=1;i<n;i++) x=read(),y=read(),insert(x,y);
        rt=1; build(1,1,n); dfs(1,0);
        char ch[15]; 
        for(int i=1;i<=m;i++){
            scanf("%s",ch); x=read();
            if(ch[2]=='Q') printf("%.10lf
    ",addup(x));
            else{
                acs(x);
                if(ch[2]=='C') mrt(x);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    [bzoj5285][Hnoi2018]寻宝游戏【复杂度分析】
    2020-2021-1 20201229《信息安全专业导论》第十二周学习总结
    2020-2021-1 20201229《信息安全专业导论》第十一周学习总结
    2020-2021-1 20201229《信息安全专业导论》第十周学习总结
    2020-2021-1 20201229 《信息安全专业导论》第九周学习总结
    熟悉编程语言
    2020-2021-1 20201229 《信息安全专业导论》第八周学习总结
    如何学好编程
    2020-2021-1 20201229 《信息安全专业导论》 第七周学习总结
    实现进制转化伪代码
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7072032.html
Copyright © 2011-2022 走看看