zoukankan      html  css  js  c++  java
  • BZOJ 3510 首都 (LCT)

    洛谷P4299传送门

    题目大意:给你一颗树,边是一条一条连上去的

    在连接过程中会存在询问,询问当前节点所在联通块(其实是一颗树)的重心是哪个节点

    以及森林中所有树的重心的异或和

    在做这道题之前,要先了解树的重心的一个性质:

    两棵树合并时,新树的重心在合并后,原来两颗树的重心的两个节点构成的那条链上

    了解了这条性质,思路就不难想了

    当连接两个节点时,先寻找它们所在原树的重心,然后连接这两个节点,在取出两个原树重心那两个节点构成的那条链

    每次寻找重心,连接节点,取出重心形成了链,复杂度约为O(logn)

    如果我们暴力跑这条链,最差的情况是每次合并时,两颗树都是等长的链,然后像线段树那样从下往上合并,合并次数最多是O(nlogn)次,注意符合条件的重心最多只有2个,且子树的大小符合单调性,当越过所有重心时,及时跳出循环防止卡常

    总复杂度O(nlog^2n)

    然而我还是喜闻乐见得被卡常了

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #define il inline
      5 #define N 200100
      6 using namespace std;
      7 
      8 int n,m,tp,num,xsum;
      9 int stk[N],que[N];
     10 
     11 struct LinkCutTree{
     12     #define ls ch[x][0]
     13     #define rs ch[x][1]
     14     int fa[N],ch[N][2],sz[N],sum[N],rv[N];
     15     il int idf(int x){return ch[fa[x]][0]==x?0:1;}
     16     il void rev(int x){swap(ls,rs),rv[x]^=1;}
     17     il int isroot(int x){return (ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)?1:0;}
     18     il void pushup(int x){sum[x]=sum[ls]+sum[rs]+sz[x]+1;}
     19     il void pushdown(int x)
     20     {
     21         if(rv[x]){
     22             if(ls) rev(ls);
     23             if(rs) rev(rs);
     24             rv[x]^=1;
     25         }
     26     }
     27     il void rot(int x)
     28     {
     29         int y=fa[x],ff=fa[y],px=idf(x),py=idf(y);
     30         if(!isroot(y)) ch[ff][py]=x;fa[x]=ff;
     31         ch[y][px]=ch[x][px^1],fa[ch[x][px^1]]=y;
     32         ch[x][px^1]=y,fa[y]=x;
     33         pushup(y),pushup(x);
     34     }
     35     void splay(int x)
     36     {
     37         int y=x;stk[++tp]=x;
     38         while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];}
     39         while(tp){pushdown(stk[tp--]);}
     40         while(!isroot(x))
     41         {
     42             y=fa[x];
     43             if(isroot(y)) rot(x);
     44             else if(idf(y)==idf(x)) rot(y),rot(x);
     45             else rot(x),rot(x);
     46         }
     47     }
     48     void access(int x){
     49         for(int y=0;x;y=x,x=fa[x])
     50             splay(x),sz[x]-=sum[y],sz[x]+=sum[ch[x][1]],ch[x][1]=y,pushup(x);}
     51     il void mkroot(int x){access(x),splay(x),rev(x);}
     52     il void split(int x,int y){mkroot(y),access(x),splay(x);}
     53     il int findrt(int x){
     54         access(x),splay(x);
     55         while(1){
     56             pushdown(x);
     57             if(!ch[x][0])break;
     58             x=ch[x][0];}
     59         splay(x);return x;
     60     }
     61     void mid_dfs(int x)
     62     {
     63         pushdown(x);
     64         if(ls) mid_dfs(ls);
     65         que[++num]=x;
     66         if(rs) mid_dfs(rs);
     67     }
     68     il void link(int x,int y)
     69     {
     70         int gx=findrt(x),gy=findrt(y);
     71         xsum=xsum^gx^gy;
     72         if(sum[gx]<sum[gy]) swap(x,y),swap(gx,gy);
     73         split(x,y),fa[y]=x,sz[x]+=sum[y],pushup(x);
     74         num=0,split(gy,gx),mid_dfs(gy);
     75         int ma=sum[gy]/2,ans=0x3f3f3f3f;
     76         for(int i=1;i<=num;i++){
     77             splay(que[i]);
     78             if(sum[ch[que[i]][0]]<=ma&&sum[ch[que[i]][1]]<=ma&&que[i]<ans)
     79                 ans=que[i];
     80             if(sum[ch[que[i]][0]]>ma) break;}
     81         mkroot(ans);
     82         xsum^=ans;
     83     }
     84     #undef ls
     85     #undef rs
     86 }lct;
     87 int gint()
     88 {
     89     int rett=0,fh=1;char c=getchar();
     90     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     91     while(c>='0'&&c<='9'){rett=(rett<<3)+(rett<<1)+c-'0';c=getchar();}
     92     return rett*fh;
     93 }
     94 void gchar(char str[])
     95 {
     96     int p=0;char c=getchar();
     97     while(!((c>='A'&&c<='Z')||(c>='a'&&c<='z'))){c=getchar();}
     98     while((c>='A'&&c<='Z')||(c>='a'&&c<='z')){str[p++]=c;c=getchar();}
     99     str[p]='';
    100 }
    101 
    102 int main()
    103 {
    104     scanf("%d%d",&n,&m);
    105     for(int i=1;i<=n;i++) xsum^=i;
    106     char q[10];int x,y;
    107     for(int i=1;i<=m;i++)
    108     {
    109         gchar(q);
    110         if(q[0]=='A'){
    111             x=gint(),y=gint();
    112             lct.link(x,y);
    113         }else if(q[0]=='Q'){
    114             x=gint();
    115             printf("%d
    ",lct.findrt(x));
    116         }else printf("%d
    ",xsum);
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    .net注册iis
    hdu 1081To The Max
    hdu 1312Red and Black
    hdu 1016Prime Ring Problem
    hdu 1159Common Subsequence
    hdu 1372Knight Moves
    hdu 1686Oulipo
    hdu 1241Oil Deposits
    hdu 1171Big Event in HDU
    hdu 4006The kth great number
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9697102.html
Copyright © 2011-2022 走看看