• [spojQTREE6]Query on a tree VI


    考虑如下构造:

    新建一条边$(0,1)$,并将原树以0为根建树,记$fa_{x}$为$x$的父亲(其中$1le xle n$)

    维护两棵森林,分别记作$T_{0/1}$,每一条边恰属于一棵,其中$(x,fa_{x})in T_{0}$当且仅当$x$为白色点

    此时,考虑节点$x$的答案(不妨假设$x$为白色点),即是$T_{0}$去掉$x$所在连通块根节点(深度最小的节点)后所在连通块子树大小,正确性显然

    对这两棵森林使用LCT维护,考虑修改和查询:

    1.修改时,即增加并删除一条边

    2.查询时,不妨假设$x$为白色,将$T_{0}$中$x$所在连通块内深度最小的点make_root后,不难发现即求该点右儿子子树范围内的点数,显然容易维护("子树范围"定义以及如何维护见QTREE5

    考虑如何快速找到该点,考虑保持树的形态(注意初始状态),即在make_root时不rev,那么find_root的结果即为该最浅的点

    这样在加边和删边时并不会产生影响(其实通常的LCT在加边和删边时也并不需要rev),查询时的做法上面已经给出,即find_root一下即可

    时间复杂度为$o(nlog n)$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 vector<int>v[N];
      5 int n,m,x,y,f[N],col[N];
      6 struct LCT{
      7     int fa[N],vir[N],sz[N],ch[N][2];
      8     LCT(){
      9         for(int i=1;i<N;i++)sz[i]=1;
     10     }
     11     bool check(int k){
     12         return ((ch[fa[k]][0]!=k)&&(ch[fa[k]][1]!=k));
     13     }
     14     int which(int k){
     15         return ch[fa[k]][1]==k;
     16     }
     17     void up(int k){
     18         sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+vir[k]+1;
     19     }
     20     void add_vir(int k){
     21         vir[fa[k]]+=sz[k]; 
     22     }
     23     void del_vir(int k){
     24         vir[fa[k]]-=sz[k];
     25     }
     26     void rotate(int k){
     27         int f=fa[k],g=fa[f],p=which(k);
     28         fa[k]=g;
     29         if (!check(f))ch[g][which(f)]=k;
     30         fa[ch[k][p^1]]=f,ch[f][p]=ch[k][p^1];
     31         fa[f]=k,ch[k][p^1]=f;
     32         up(f),up(k);
     33     }
     34     void splay(int k){
     35         for(int i=fa[k];!check(k);i=fa[k]){
     36             if (!check(i)){
     37                 if (which(i)==which(k))rotate(i);
     38                 else rotate(k);
     39             }
     40             rotate(k);
     41         }
     42     }
     43     void access(int k){
     44         int lst=0;
     45         while (k){
     46             splay(k);
     47             if (ch[k][1])add_vir(ch[k][1]);
     48             if (lst)del_vir(lst);
     49             ch[k][1]=lst,up(k);
     50             lst=k,k=fa[k];
     51         }
     52     }
     53     void make_root(int k){
     54         access(k);
     55         splay(k);
     56     }
     57     int find_root(int k){
     58         access(k);
     59         splay(k);
     60         while (ch[k][0])k=ch[k][0];
     61         splay(k);
     62         return k;
     63     }
     64     void add(int x,int y){
     65         make_root(x);
     66         make_root(y);
     67         fa[y]=x,add_vir(y),up(x);
     68     }
     69     void del(int x,int y){
     70         make_root(x);
     71         access(y);
     72         fa[y]=ch[x][1]=0,up(x);
     73     }
     74     int query(int k){
     75         k=find_root(k);
     76         return sz[ch[k][1]];
     77     }
     78 }T[2];
     79 void dfs(int k,int fa){
     80     f[k]=fa;
     81     for(int i=0;i<v[k].size();i++)
     82         if (v[k][i]!=fa)dfs(v[k][i],k);
     83 }
     84 int main(){
     85     scanf("%d",&n);
     86     for(int i=1;i<n;i++){
     87         scanf("%d%d",&x,&y);
     88         v[x].push_back(y);
     89         v[y].push_back(x);
     90     }
     91     dfs(1,n+1);
     92     for(int i=1;i<=n;i++){
     93         col[i]=1;
     94         T[1].add(f[i],i);
     95     }
     96     scanf("%d",&m);
     97     for(int i=1;i<=m;i++){
     98         scanf("%d%d",&x,&y);
     99         if (!x)printf("%d
    ",T[col[y]].query(y));
    100         else{
    101             T[col[y]].del(f[y],y);
    102             col[y]^=1;
    103             T[col[y]].add(f[y],y);
    104         }
    105     }
    106     return 0;
    107 }
    View Code
  • 相关阅读:
    c#函数重载
    (1).net c# 一步一步自己写三层代码生成器(主界面及连接数据库界面)
    C#给datagridview某行赋值(转)
    好的软件人员必看的六十本书
    C# 语言规范
    spring 排除指定的类或者包扫描
    java web spring 发送邮件
    spring-data-redis和jedis版本对应收集总结
    python 多线程和多进程基本写法
    python 调用nmap
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15337520.html
Copyright © 2020-2023  润新知