• [洛谷P4299] 首都


    题目传送门

    还是维护子树信息。

    但是这里多了一个找重心的操作。

    这里有一个关于树重心的结论,据说可以用反证法证明。反正我不会证

    就是:新的重心一定在原来两个重心之间的那条树链上。

    这样我们逐步缩小搜索范围,就可以很快地找到新树的重心了。

    另外,每次找重心太慢了,用并查集维护一下每个点所在的树重心。

    其他的就没什么特别了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define id(x) (s[f[x]][1]==x)
      5 using namespace std;
      6 
      7 int n,m;
      8 int s[100005][2],f[100005];
      9 int sz[100005],szi[100005];
     10 int rev[100005],rt[100005];
     11 int ff[100005];
     12 
     13 int findfa(int x)
     14 {
     15     if(x==ff[x])return x;
     16     ff[x]=findfa(ff[x]);
     17     return ff[x];
     18 }
     19 
     20 void pushup(int p)
     21 {
     22     sz[p]=sz[s[p][0]]+sz[s[p][1]]+szi[p]+1;
     23 }
     24 
     25 void reverse(int p)
     26 {
     27     swap(s[p][0],s[p][1]);
     28     rev[p]^=1;
     29 }
     30 
     31 void pushdown(int p)
     32 {
     33     if(!rev[p])return;
     34     reverse(s[p][0]);
     35     reverse(s[p][1]);
     36     rev[p]=0;
     37 }
     38 
     39 void rotate(int p)
     40 {
     41     int k=id(p);
     42     int fa=f[p];
     43     if(rt[fa])rt[p]=1,rt[fa]=0;
     44     else s[f[fa]][id(fa)]=p;
     45     s[fa][k]=s[p][!k];
     46     s[p][!k]=fa;
     47     f[p]=f[fa];
     48     f[fa]=p;
     49     f[s[fa][k]]=fa;
     50     pushup(fa);
     51     pushup(p);
     52 }
     53 
     54 void down(int p)
     55 {
     56     if(!rt[p])down(f[p]);
     57     pushdown(p);
     58 }
     59 
     60 void splay(int p)
     61 {
     62     down(p);
     63     while(!rt[p])
     64     {
     65         int fa=f[p];
     66         if(rt[fa])
     67         {
     68             rotate(p);
     69             return;
     70         }
     71         if(id(p)^id(fa))rotate(p);
     72         else rotate(fa);
     73         rotate(p);
     74     }
     75 }
     76 
     77 void access(int p)
     78 {
     79     int son=0;
     80     while(p)
     81     {
     82         splay(p);
     83         szi[p]+=sz[s[p][1]];
     84         rt[s[p][1]]=1,rt[son]=0;
     85         s[p][1]=son;
     86         szi[p]-=sz[s[p][1]];
     87         pushup(p);
     88         son=p,p=f[p];
     89     }
     90 }
     91 
     92 void mtr(int p)
     93 {
     94     access(p);
     95     splay(p);
     96     reverse(p);
     97 }
     98 
     99 void isolate(int x,int y)
    100 {
    101     mtr(x);
    102     access(y);
    103     splay(y);
    104 }
    105 
    106 int nueva(int p)
    107 {
    108     int l,r,sum=sz[p]>>1,tot=sz[p]&1,lsum=0,rsum=0,ng=n+1,nl,nr;
    109     while(p)
    110     {
    111         pushdown(p);
    112         l=s[p][0],r=s[p][1];
    113         nl=sz[l]+lsum,nr=sz[r]+rsum;
    114         if(nl<=sum&&nr<=sum)
    115         {
    116             if(tot)
    117             {
    118                 ng=p;
    119                 break;
    120             }else
    121             if(ng>p)ng=p;
    122         }
    123         if(nl<nr)lsum+=sz[l]+szi[p]+1,p=r;
    124         else rsum+=sz[r]+szi[p]+1,p=l;
    125     }
    126     splay(ng);
    127     return ng;
    128 }
    129 
    130 int xsum;
    131 
    132 int main()
    133 {
    134     scanf("%d%d",&n,&m);
    135     for(int i=1;i<=n;i++)
    136     {
    137         sz[i]=rt[i]=1;
    138         ff[i]=i;
    139         xsum^=i;
    140     }
    141     for(int i=1;i<=m;i++)
    142     {
    143         char op[5];
    144         scanf("%s",op+1);
    145         if(op[1]=='A')
    146         {
    147             int x,y;
    148             scanf("%d%d",&x,&y);
    149             isolate(x,y);
    150             f[x]=y;
    151             szi[y]+=sz[x];
    152             pushup(y);
    153             x=findfa(x),y=findfa(y);
    154             isolate(x,y);
    155             int ng=nueva(y);
    156             xsum=xsum^x^y^ng;
    157             ff[x]=ff[y]=ff[ng]=ng;
    158         }
    159         if(op[1]=='Q')
    160         {
    161             int x;
    162             scanf("%d",&x);
    163             printf("%d
    ",findfa(x));
    164         }
    165         if(op[1]=='X')printf("%d
    ",xsum);
    166     }
    167     return 0;
    168 }
  • 相关阅读:
    1301班 github安装及账户注册
    对于软件工程课程的疑问
    LeetCode50:Pow
    LeetCode49:字母异位词分组
    LeetCode46:全排列
    LeetCode38:外观数列
    LeetCode:有效的数独
    LeetCode34:在排序数组中查找元素的第一个位置和最后一个位置
    LeetCode33:搜索旋转排序数组
    LeetCode29:两数相除
  • 原文地址:https://www.cnblogs.com/cervusy/p/9674664.html
Copyright © 2020-2023  润新知