• bzoj4817/luogu3703 树点涂色 (LCT+dfs序+线段树)


    我们发现,这个染色的操作他就很像LCT中access的操作(为什么??),然后就自然而然地想到,其实一个某条路径上的颜色数量,就是我们做一个只有access操作的LCT,这条路径经过的splay的数量

    然后考虑怎么样来维护这个数量。access的过程中,有实边变虚边、虚边变实边的操作,对应过来,实边变虚边,就是以(断掉的那个子splay树中的在原树中最浅的点)为根的子树中 每个点到根的颜色数++(多拆出来了一个splay嘛),虚边变实边同理,不过是--

    这样就可以再用一个线段树维护dfs序了,第三个询问就是线段树上的最大值

    第二个询问,如果有x,y,lca,那x到y路径上的颜色数就是num[x]+num[y]-2*num[lca]+1,num[i]就是刚才线段树记的那个

      1 #include<bits/stdc++.h>
      2 #define pa pair<int,int>
      3 #define CLR(a,x) memset(a,x,sizeof(a))
      4 using namespace std;
      5 typedef long long ll;
      6 const int maxn=1e5+10;
      7 
      8 inline ll rd(){
      9     ll x=0;char c=getchar();int neg=1;
     10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     12     return x*neg;
     13 }
     14 
     15 int N,M;
     16 int eg[maxn*2][2],egh[maxn],ect;
     17 int dep[maxn],dfn[maxn][2],fa[maxn],ch[maxn][2],tot;
     18 int bf[maxn][20],ma[maxn*4],laz[maxn*4],id[maxn];
     19 
     20 inline void adeg(int a,int b){
     21     eg[++ect][0]=b,eg[ect][1]=egh[a];egh[a]=ect;
     22 }
     23 
     24 void dfs(int x){
     25     dfn[x][0]=++tot;id[tot]=x;
     26     for(int i=0;bf[x][i]&&bf[bf[x][i]][i];i++)
     27         bf[x][i+1]=bf[bf[x][i]][i];
     28     for(int i=egh[x];i;i=eg[i][1]){
     29         int b=eg[i][0];
     30         if(b==fa[x]) continue;
     31         fa[b]=bf[b][0]=x;dep[b]=dep[x]+1;
     32         dfs(b);
     33     }
     34     dfn[x][1]=tot;
     35 }
     36 
     37 inline int getlca(int x,int y){
     38     if(dep[x]<dep[y]) swap(x,y);
     39     for(int i=log2(dep[x]-dep[y]);i>=0&&dep[x]!=dep[y];i--){
     40         if(dep[bf[x][i]]>=dep[y])
     41             x=bf[x][i];
     42     }
     43     if(x==y) return x;
     44     for(int i=log2(dep[x]);i>=0;i--){
     45         if(bf[x][i]!=bf[y][i])
     46             x=bf[x][i],y=bf[y][i];
     47     }
     48     return bf[x][0];
     49 }
     50 
     51 inline bool nroot(int x){return x==ch[fa[x]][0]||x==ch[fa[x]][1];}
     52 inline bool isrt(int x){return x==ch[fa[x]][1];}
     53 
     54 inline void rotate(int x){
     55     int f=fa[x],ff=fa[fa[x]];bool b=isrt(x);
     56     fa[x]=ff;if(nroot(f)) ch[ff][isrt(f)]=x;
     57     fa[ch[x][!b]]=f,ch[f][b]=ch[x][!b];
     58     fa[f]=x,ch[x][!b]=f;
     59 }
     60 
     61 inline void splay(int x){
     62     while(nroot(x)&&nroot(fa[x])){
     63         if(isrt(x)==isrt(fa[x])) rotate(fa[x]);
     64         else rotate(x);rotate(x);
     65     }if(nroot(x)) rotate(x);
     66 }
     67 
     68 inline int getl(int x){
     69     while(ch[x][0]) x=ch[x][0];
     70     return x;
     71 }
     72 
     73 inline void update(int p){ma[p]=max(ma[p<<1],ma[p<<1|1]);}
     74 inline void pushdown(int p){
     75     if(!laz[p]) return;
     76     int a=p<<1,b=p<<1|1;
     77     laz[a]+=laz[p],laz[b]+=laz[p];
     78     ma[a]+=laz[p],ma[b]+=laz[p];
     79     laz[p]=0;
     80 }
     81 
     82 inline void build(int p,int l,int r){
     83     if(l==r) ma[p]=dep[id[l]];
     84     else{
     85         int m=l+r>>1;
     86         build(p<<1,l,m);
     87         build(p<<1|1,m+1,r);
     88         update(p);
     89     }
     90 }
     91 inline void add(int p,int l,int r,int x,int y,int z){
     92     // printf("%d %d %d %d %d
    ",p,l,r,x,y);
     93     if(x<=l&&r<=y){
     94         ma[p]+=z;laz[p]+=z;
     95     }else{
     96         pushdown(p);
     97         int m=l+r>>1;
     98         if(x<=m) add(p<<1,l,m,x,y,z);
     99         if(y>=m+1) add(p<<1|1,m+1,r,x,y,z);
    100         update(p);
    101     }
    102 }
    103 inline int query(int p,int l,int r,int x,int y){
    104     if(!x||!y) return 0;
    105     if(x<=l&&r<=y) return ma[p];
    106     pushdown(p);
    107     int m=l+r>>1,re=0;
    108     if(x<=m) re=query(p<<1,l,m,x,y);
    109     if(y>=m+1) re=max(re,query(p<<1|1,m+1,r,x,y));
    110     return re;
    111 }
    112 
    113 inline void access(int x){
    114     for(int y=0;x;y=x,x=fa[x]){
    115         splay(x);
    116         int a=getl(ch[x][1]),b=getl(y);
    117         // printf("!%d %d
    ",a,b);
    118         if(a) add(1,1,N,dfn[a][0],dfn[a][1],1);
    119         if(b) add(1,1,N,dfn[b][0],dfn[b][1],-1);
    120         ch[x][1]=y;
    121     }
    122 }
    123 
    124 inline int gettop(int x){
    125     while(nroot(x)) x=fa[x];
    126     return x;
    127 }
    128 
    129 int main(){
    130     //freopen("","r",stdin);
    131     int i,j,k;
    132     N=rd(),M=rd();
    133     for(i=1;i<N;i++){
    134         int a=rd(),b=rd();
    135         adeg(a,b);adeg(b,a);
    136     }
    137     dep[1]=1;dfs(1);
    138     build(1,1,N);
    139     for(i=1;i<=M;i++){
    140         int a=rd(),x=rd();
    141         if(a==1)  access(x);
    142         else if(a==2){
    143             int y=rd();
    144             int lca=getlca(x,y);
    145             // printf("%d %d
    ",x,y)
    146             printf("%d
    ",query(1,1,N,dfn[x][0],dfn[x][0])+
    147                 query(1,1,N,dfn[y][0],dfn[y][0])-
    148                 2*query(1,1,N,dfn[lca][0],dfn[lca][0])+1);
    149         }else{
    150             printf("%d
    ",query(1,1,N,dfn[x][0],dfn[x][1]));
    151         }
    152     }
    153     return 0;
    154 }
  • 相关阅读:
    Sql Server 创建表(可重复执行--范本)
    Sql Server 存储过程(可重复执行--范本)
    table设置了colspan之后出现td宽度显示不正常
    textarea 自适应高度
    获取系统文件
    牛客网前端编程:计算给定数组 arr 中所有元素的总和
    牛客网前端编程:删除数组中特定元素
    牛客网前端编程:找出元素 item 在给定数组 arr 中的位置
    element+vue:将Unix时间戳转化标准格式
    vue-router使用
  • 原文地址:https://www.cnblogs.com/Ressed/p/9816421.html
Copyright © 2020-2023  润新知