BZOJ[3779]重组病毒

2 篇文章 0 订阅

留坑,以后一定会回来调的

#include<algorithm>
#include<assert.h>
#include<ctype.h>
#include<cstdio>
#define INF 2147483647
#define N 200020
using namespace std;
inline int read(){
    int x=0,f=1;char c;
    do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
    do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
    return x*f;
}
int n,m,x,y,id,top,T;
int fir[N],dfn[N],siz[N],f[N][21],dep[N],pret[N];
char s[105];
struct Edge{
    int to,nex;
    Edge(){}
    Edge(int to,int nex):to(to),nex(nex){}
}nex[N<<1];
struct SNode{
    SNode *ls,*rs;
    int sum,v;
    SNode():ls(NULL),rs(NULL),sum(0),v(0){}
    inline void maintain(){
        sum=ls->sum+rs->sum;
    }
    inline void pushdown(int L,int R){
        if(v){
            int mid=(L+R)>>1;
            ls->v+=v;rs->v+=v;
            ls->sum+=(mid-L+1)*v;rs->sum+=(R-(mid+1)+1)*v;
            v=0;
        }
    }
}*root;
struct Node{
    Node *fa,*ch[2];
    int id,l,r;bool rev;
    Node(int);
    inline int dir(){
        if(fa->ch[0]==this) return 0;
        if(fa->ch[1]==this) return 1;
        return -1;
    }
    inline void maintain(){
        l=min(dfn[id],min(ch[0]->l,ch[1]->l));
        r=max(dfn[id],max(ch[0]->r,ch[1]->r));
    }
    inline void pushdown();
}*pre[N],*null;
Node::Node(int x):id(x){
    fa=ch[0]=ch[1]=null;
    rev=false;
}
inline void Node::pushdown(){
    if(rev){
        if(ch[0]!=null){
            ch[0]->rev^=1;
            swap(ch[0]->ch[0],ch[0]->ch[1]);
        }
        if(ch[1]!=null){
            ch[1]->rev^=1;
            swap(ch[1]->ch[0],ch[1]->ch[1]);
        }
        rev=0;
    }
}
inline void init(){
    null=new Node(0);
    null->ch[0]=null->ch[1]=null->fa=null;
    null->r=-1;null->l=INF;
    pre[0]=null;
}
inline void add(int x,int y){
    nex[++top]=Edge(y,fir[x]);
    fir[x]=top;
}
void dfs(int x,int fa){
    dfn[x]=++T;siz[x]=1;pret[T]=x;
    f[x][0]=fa;dep[x]=dep[fa]+1;
    pre[x]=new Node(x);
    pre[x]->fa=pre[fa];
    pre[x]->l=pre[x]->r=dfn[x];
    for(int i=fir[x];i;i=nex[i].nex){
        if(nex[i].to==fa) continue;
        dfs(nex[i].to,x);
        siz[x]+=siz[nex[i].to];
    }
}
void build(int L,int R,SNode *&k){
    k=new SNode();
    if(L==R) return void(k->sum=dep[pret[L]]);
    int mid=(L+R)>>1;
    build(L,mid,k->ls);build(mid+1,R,k->rs);
    k->maintain();
}
void Add(int L,int R,int x,int y,int v,SNode *k){
    if(L>=x && R<=y){
        k->sum+=(R-L+1)*v;
        k->v+=v;
        return;
    }
    int mid=(L+R)>>1;
    k->pushdown(L,R);
    if(y<=mid) Add(L,mid,x,y,v,k->ls);
    else if(x>mid) Add(mid+1,R,x,y,v,k->rs);
    else Add(L,mid,x,y,v,k->ls),Add(mid+1,R,x,y,v,k->rs);
    k->maintain();
}
inline int Query(int L,int R,int x,int y,SNode *k){
    if(L>=x && R<=y) return k->sum;
    int mid=(L+R)>>1;
    k->pushdown(L,R);
    if(y<=mid) return Query(L,mid,x,y,k->ls);
    else if(x>mid) return Query(mid+1,R,x,y,k->rs);
    else return Query(L,mid,x,y,k->ls)+Query(mid+1,R,x,y,k->rs);
}
inline int LCA(int x,int y){
    if(dep[x]<dep[y]) return LCA(y,x);
    for(int i=20;~i;i--)
        if(dep[f[x][i]]>=dep[y])
            x=f[x][i];
    if(x==y) return x;
    for(int i=20;~i;i--)
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    return f[x][0];
}
inline void Add_Tree(int x,int v){
    if(x>0 && x<=n){
        //printf("%d %d\n",x,v);
        int t=x;
        if(t==id) Add(1,n,1,n,v,root);
        else{
            int y=LCA(t,id);
            if(t==y){
                y=id;
                for(int j=20;~j;j--)
                    if(dep[f[y][j]]>dep[x])
                        y=f[y][j];
                //printf("ooooo%d\n",y);
                Add(1,n,1,n,v,root);Add(1,n,dfn[y],dfn[y]+siz[y]-1,-v,root);
            }
            else Add(1,n,dfn[t],dfn[t]+siz[t]-1,v,root);
        }
    }
}
inline void Rotate(Node *x,int d){
    Node *k=x->ch[d^1];
    int tmp;
    x->ch[d^1]=k->ch[d];
    if(x->ch[d^1]!=null) x->ch[d^1]->fa=x;
    k->ch[d]=x;
    if(~(tmp=x->dir())) x->fa->ch[tmp]=k;
    k->fa=x->fa;x->fa=k;
    x->maintain();k->maintain();
}
inline void To_Pushdown(Node *x){
    if(~x->dir()) To_Pushdown(x->fa);
    x->pushdown();
    return;
}
inline void Splay(Node *x){
    assert(x!=null);
    To_Pushdown(x);
    int tmp;
    while(~(tmp=x->dir())){
        while(x->fa->dir()==tmp)
            Rotate(x->fa->fa,tmp^1);
        Rotate(x->fa,tmp^1);
    }
    return;
}
inline void Access(Node *x){
    Node *pre=null;
    while(x!=null){
        //printf("pp%d\n",x->id);
        Splay(x);
        Add_Tree(pre->id,-1);
        Add_Tree(x->ch[1]->id,1);
        x->ch[1]=pre;pre=x;
        x=x->fa;
    }
    return;
}
inline void Make_root(Node *x){
    Access(x);Splay(x);
    x->rev^=1;swap(x->ch[0],x->ch[1]);
    return;
}
inline void init_LCA(){
    for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++)
            f[i][j]=f[f[i][j-1]][j-1];
    return;
}
int main(){
    n=read();m=read();
    for(int i=1;i<n;i++){
        x=read();y=read();
        add(x,y);add(y,x);
    }
    id=1;
    init();
    dfs(1,0);build(1,n,root);
    init_LCA();
    for(int i=1;i<=m;i++){
        scanf("%s",s+1);x=read();
        if(s[3]=='L') Access(pre[x]);
        else if(s[3]=='C'){
            Make_root(pre[x]);id=x;
        }
        else{
            if(x==id) printf("%.10lf\n",1.0*Query(1,n,1,n,root)/(1.0*n));
            else{
                y=LCA(x,id);
                if(x==y){
                    y=id;
                    for(int j=20;~j;j--)
                        if(dep[f[y][j]]>dep[x])
                            y=f[y][j];
                    printf("%.10lf\n",1.0*(Query(1,n,1,n,root)-Query(1,n,dfn[y],dfn[y]+siz[y]-1,root))/(1.0*(n-siz[y])));
                }
                else printf("%.10lf\n",1.0*Query(1,n,dfn[x],dfn[x]+siz[x]-1,root)/(1.0*siz[x]));
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值