xsy1025 link-cut-tree+线段树

来源:互联网 发布:脱口秀大会 知乎 编辑:程序博客网 时间:2024/06/07 06:10

题意:

这里写图片描述

分析:

这里写图片描述
这里写图片描述

代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=200100;typedef long long ll;int fa[N],c[N][2],rev[N],q[N];int dep[N],a[N][21],h[N],w[N],lst[N],tmp[N];ll sum[N*4];int tag[N*4],sz[N*4];int n,m,tot,x,y,tm,root=1;struct edge{int y,next;}g[N];char s[100];void adp(int x,int y){    g[++tot].y=y;    g[tot].next=h[x];    h[x]=tot;}void dfs(int x){    fa[x]=a[x][0];w[x]=++tm;    tmp[tm]=tmp[w[a[x][0]]]+1;    for (int i=h[x];i;i=g[i].next)    if (g[i].y!=a[x][0]){        dep[g[i].y]=dep[x]+1;        a[g[i].y][0]=x;        dfs(g[i].y);    }    lst[x]=tm;}/*----------------线段树-------------------*/void pushup(int rt){    sum[rt]=sum[2*rt]+sum[2*rt+1];}void tagg(int rt,int val){    sum[rt]+=(ll)val*sz[rt];    tag[rt]+=val;}void pushdown(int rt){    if (tag[rt]){        tagg(2*rt,tag[rt]);        tagg(2*rt+1,tag[rt]);        tag[rt]=0;    }}void build(int rt,int l,int r){    if (l==r){sum[rt]=tmp[l],sz[rt]=1;return;}    int mid=(l+r)>>1;    build(2*rt,l,mid);build(2*rt+1,mid+1,r);    pushup(rt);sz[rt]=sz[2*rt]+sz[2*rt+1];} void change(int rt,int l,int r,int ll,int rr,int val){    if (ll>rr) return;    if (ll==l && r==rr){tagg(rt,val);return;}    pushdown(rt);    int mid=(l+r)>>1;    if (ll<=mid) change(2*rt,l,mid,ll,min(rr,mid),val);    if (rr> mid) change(2*rt+1,mid+1,r,max(mid+1,ll),rr,val);    pushup(rt);}void change(int rt,int k){    if (rt==root) change(1,1,n,1,n,k); else    if (w[root]>w[rt] && w[root]<=lst[rt]){        int t=root;        for (int i=20;i>=0;i--)        if ((dep[t]-dep[rt]-1)&(1<<i))            t=a[t][i];        change(1,1,n,1,w[t]-1,k);        change(1,1,n,lst[t]+1,n,k);    } else change(1,1,n,w[rt],lst[rt],k);}ll query(int rt,int l,int r,int ll,int rr){    if (ll>rr) return 0;    if (ll==l && r==rr) return sum[rt];    pushdown(rt);    int mid=(l+r)>>1;long long res=0;    if (ll<=mid) res+=query(2*rt,l,mid,ll,min(mid,rr));    if (rr> mid) res+=query(2*rt+1,mid+1,r,max(mid+1,ll),rr);    return res;}double query(int rt){    if (rt==root) return 1.0*query(1,1,n,1,n)/n;     if (w[root]>w[rt] && w[root]<=lst[rt]){        int t=root;        for (int i=20;i>=0;i--)        if ((dep[t]-dep[rt]-1)&(1<<i))            t=a[t][i];        int size=w[t]-1+n-lst[t];        return 1.0*((query(1,1,n,1,w[t]-1)+query(1,1,n,lst[t]+1,n)))/size;    }    return 1.0*query(1,1,n,w[rt],lst[rt])/(lst[rt]-w[rt]+1);}/*--------------------线段树-------------------------*//*---------------------lct---------------------------*/int isroot(int x){    return c[fa[x]][0]!=x && c[fa[x]][1]!=x;}void push_down(int x){    if (rev[x]){        rev[x]^=1;        rev[c[x][0]]^=1;        rev[c[x][1]]^=1;        swap(c[x][0],c[x][1]);    }}void rotate(int x){    int y=fa[x],z=fa[y];    int l,r;    if (c[fa[x]][0]==x)        l=0; else l=1;    r=l^1;    if (!isroot(y)) {        if (c[z][0]==y)            c[z][0]=x; else            c[z][1]=x;    }    fa[x]=z;fa[y]=x;    fa[c[x][r]]=y;    c[y][l]=c[x][r];    c[x][r]=y;}void splay(int x){    int top=0,t=x;    q[++top]=x;    while (!isroot(t)){        q[++top]=fa[t];        t=fa[t];    }    for (int i=top;i;i--)        push_down(q[i]);    while (!isroot(x)){        int y=fa[x],z=fa[y];        if (!isroot(y)) {            if ((c[z][0]==y)!=(c[y][0]==x))                rotate(x); else                rotate(y);        }        rotate(x);    }}int find(int x){    int t=x;push_down(x);    while (c[t][0]){        t=c[t][0];        push_down(t);    }    return t;}void access(int x){    int t=0;    while (x){        splay(x);        if (c[x][1]) change(find(c[x][1]),1);        c[x][1]=t;        if (t) change(find(t),-1);        t=x;x=fa[x];    }}void makeroot(int x){    access(x);    splay(x);    rev[x]^=1;    root=x;}/*---------------------lct-----------------------*/int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<n;i++){        scanf("%d%d",&x,&y);        adp(x,y);adp(y,x);    }    tmp[1]=1;dfs(1);    for (int j=1;j<=20;j++)         for (int i=1;i<=n;i++)            a[i][j]=a[a[i][j-1]][j-1];    build(1,1,n);    while (m--){        scanf("%s%d",s,&x);        if (s[2]=='L')            access(x);        if (s[2]=='C')            makeroot(x);        if (s[2]=='Q')            printf("%.10lf\n",query(x));    }}
原创粉丝点击