zoukankan      html  css  js  c++  java
  • [BZOJ4530][Bjoi2014]大融合(LCT)

    传送门

    大佬们似乎都是用树剖+并查集优雅地A了此题

    然后我太弱了,只能打打LCT的板子

    虽然的确可以挺无脑的A掉……

    不过至少这题教了我该怎么维护LCT上虚子树的信息,具体看这里

    首先,答案很明显是断开边后两个子树的大小之积

    所以只要把这条边split出来,答案就是$(size[y]-size[x])*size[x]$(很好理解)

    或者$x的虚子树大小*y的虚子树大小$(我用的是这种方法,为什么的话,代码里有注解)

     1 //minamoto
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define ll long long
     6 using namespace std;
     7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     8 char buf[1<<21],*p1=buf,*p2=buf;
     9 inline int read(){
    10     #define num ch-'0'
    11     char ch;bool flag=0;int res;
    12     while(!isdigit(ch=getc()))
    13     (ch=='-')&&(flag=true);
    14     for(res=num;isdigit(ch=getc());res=res*10+num);
    15     (flag)&&(res=-res);
    16     #undef num
    17     return res;
    18 }
    19 char obuf[1<<24],*o=obuf;
    20 inline void print(ll x){
    21     if(x>9) print(x/10);
    22     *o++=x%10+48;
    23 }
    24 const int N=100005;
    25 int fa[N],ch[N][2],s[N],rev[N],top,sum[N],summ[N];
    26 inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    27 inline void pushup(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+summ[x]+1;}
    28 inline void pushdown(int x){
    29     if(x&&rev[x]){
    30         swap(ch[x][0],ch[x][1]);
    31         rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
    32         rev[x]=0;
    33     }
    34 }
    35 void rotate(int x){
    36     int y=fa[x],z=fa[y],d=ch[y][1]==x;
    37     if(!isroot(y)) ch[z][ch[z][1]==y]=x;
    38     fa[x]=z,fa[y]=x,fa[ch[x][d^1]]=y,ch[y][d]=ch[x][d^1],ch[x][d^1]=y,pushup(y);
    39 }
    40 void splay(int x){
    41     s[top=1]=x;for(int i=x;!isroot(i);i=fa[i]) s[++top]=fa[i];
    42     while(top) pushdown(s[top--]);
    43     for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){
    44         if(!isroot(y))
    45         ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y);
    46         rotate(x);
    47     }
    48     pushup(x);
    49 }
    50 inline void access(int x){
    51     for(int y=0;x;x=fa[y=x])
    52     splay(x),summ[x]+=sum[ch[x][1]],summ[x]-=sum[ch[x][1]=y];
    53 }
    54 inline void makeroot(int x){
    55     access(x),splay(x),rev[x]^=1;
    56 }
    57 inline void split(int x,int y){
    58     makeroot(x),access(y),splay(y);
    59 }
    60 inline void link(int x,int y){
    61     split(x,y),summ[fa[x]=y]+=sum[x],pushup(y);
    62 }
    63 int main(){
    64     //freopen("testdata.in","r",stdin);
    65     int n=read(),m=read();
    66     for(int i=1;i<=n;++i) sum[i]=1;
    67     while(m--){
    68         char ch;int u,v;
    69         ch=getc(),u=read(),v=read();
    70         if(ch=='A') link(u,v);
    71         else split(u,v),print(1ll*(summ[u]+1)*(summ[v]+1)),*o++='
    ';
    72         /*split之后splay中肯定只有u,v两点
    73         然后虚子树中的点数就相当于cut之后两点各自的子树大小
    74         然后又因为u和v都已经被splay过了,肯定没有点在它上面*/
    75     }
    76     fwrite(obuf,o-obuf,1,stdout);
    77     return 0;
    78 }
  • 相关阅读:
    关于浏览器及系统的判断
    toggle与slideToggle
    安卓与ios的不同处理
    关于常用循环遍历获取数据
    docker
    Mysql
    rabbitMQ的使用转载
    Git命令行
    vue项目创建完整版
    redis操作(str.hash.list.set)
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9417971.html
Copyright © 2011-2022 走看看