zoukankan      html  css  js  c++  java
  • BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)

    题目大意:略

    涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上

    用$LCT$维护一个树上集合就好

    因为它维护了树上集合,所以它别的啥都干不了了

    发现树是静态的,可以用$dfs$序搞搞

    把问题当成树上节点涂色会很麻烦

    但只有相邻的不同颜色节点才会对答案产生影响

    所以我们把涂色当成一种连边/断边操作

    这样,问题就容易解决得多了

    维护一个数组$f_{x}$表示$x$节点到根的路径上一共有$f_{x}$种颜色,$f_{x}-1$条断边

    显然它的初始值就是节点x的深度

    第一个操作,把这个位置到根打通

    每断一条边,子树每个节点答案$+1$,连一条边,答案$-1$

    在$access$操作中进行讨论即可

    第二个操作,求链上不同颜色数量,即一个链的断边数量$-1$

    显然,答案是$(f_{x}-1)+(f_{y}-1)-2*(f_{lca(x,y)}-1)+1=f_{x}+f_{y}-2*f_{lca(x,y)}+1$

    即断边总数$+1$

    不要把它当成节点的颜色去想

    第三个操作,求子树内$f_{x}$最大值

    以上操作皆可用$dfs$序+线段树实现!

    随时保持清醒头脑,千万不要把这个$LCT$当成真正的$LCT$,它只是一个维护链集合的媒介!

    尤其是断边/连边,进行区间修改操作时,需要找出开头/后继节点,而不是当前splay的根节点

      1 #include <queue>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #define N1 101000
      7 #define S1 (N1<<1)
      8 #define T1 (N1<<2)
      9 #define ll long long
     10 #define uint unsigned int
     11 #define rint register int 
     12 #define ull unsigned long long
     13 #define dd double
     14 #define il inline 
     15 #define inf 1000000000
     16 using namespace std;
     17 
     18 int gint()
     19 {
     20     int ret=0,fh=1;char c=getchar();
     21     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     22     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     23     return ret*fh;
     24 }
     25 int n,m,T;
     26 struct Edge{
     27 int to[N1*2],nxt[N1*2],head[N1],cte;
     28 void ae(int u,int v)
     29 {cte++;to[cte]=v,nxt[cte]=head[u],head[u]=cte;}
     30 }E;
     31 
     32 struct SEG{
     33 int ma[N1<<2],tag[N1<<2];
     34 void pushup(int rt){ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);}
     35 void pushdown(int rt)
     36 {
     37     if(!tag[rt]) return;
     38     ma[rt<<1]+=tag[rt]; ma[rt<<1|1]+=tag[rt];
     39     tag[rt<<1]+=tag[rt]; tag[rt<<1|1]+=tag[rt];
     40     tag[rt]=0;
     41 }
     42 void build(int *a,int *id,int l,int r,int rt)
     43 {
     44     if(l==r) {ma[rt]=a[id[l]];return;}
     45     int mid=(l+r)>>1;
     46     build(a,id,l,mid,rt<<1);
     47     build(a,id,mid+1,r,rt<<1|1);
     48     pushup(rt);
     49 }
     50 void update(int L,int R,int l,int r,int rt,int w)
     51 {
     52     if(!L||!R||L>R) return;
     53     if(L<=l&&r<=R) {ma[rt]+=w,tag[rt]+=w;return;}
     54     int mid=(l+r)>>1; pushdown(rt);
     55     if(L<=mid) update(L,R,l,mid,rt<<1,w);
     56     if(R>mid) update(L,R,mid+1,r,rt<<1|1,w);
     57     pushup(rt);
     58 }
     59 int query(int L,int R,int l,int r,int rt)
     60 {
     61     if(L<=l&&r<=R) return ma[rt];
     62     int mid=(l+r)>>1,ans=0; pushdown(rt);
     63     if(L<=mid) ans=max(ans,query(L,R,l,mid,rt<<1));
     64     if(R>mid) ans=max(ans,query(L,R,mid+1,r,rt<<1|1));
     65     return ans;
     66 }
     67 }s;
     68 
     69 namespace lct{
     70 int ch[N1][2],fa[N1];
     71 int idf(int x){return ch[fa[x]][0]==x?0:1;}
     72 int isroot(int x){return (ch[fa[x]][0]==x||ch[fa[x]][1]==x)?0:1;}
     73 //int stk[N1],tp;
     74 void rot(int x)
     75 {
     76     int y=fa[x],ff=fa[y],px=idf(x),py=idf(y);
     77     if(!isroot(y)) ch[ff][py]=x; fa[x]=ff; 
     78     fa[ch[x][px^1]]=y,ch[y][px]=ch[x][px^1];
     79     ch[x][px^1]=y,fa[y]=x;
     80     //pushup(y),pushup(x);
     81 }
     82 void splay(int x)
     83 {
     84     int y=x; /*stk[++tp]=x;
     85     while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];}
     86     while(tp){pushdown(stk[tp--]);}*/
     87     while(!isroot(x))
     88     {
     89         y=fa[x];
     90         if(isroot(y)) rot(x);
     91         else if(idf(y)==idf(x)) rot(y),rot(x);
     92         else rot(x),rot(x);
     93     }
     94 }
     95 int First(int x){while(ch[x][0]) x=ch[x][0];return x;}
     96 int upper(int x){x=ch[x][1];while(ch[x][0]) x=ch[x][0];return x;}
     97 void access(int x,int *st,int *ed)
     98 {
     99     for(int y=0,z;x;)
    100     {
    101         splay(x);
    102         z=upper(x);
    103         if(z) s.update(st[z],ed[z],1,n,1,1);
    104         z=First(y);
    105         s.update(st[z],ed[z],1,n,1,-1);
    106         ch[x][1]=y; y=x; x=fa[x]; 
    107     }
    108 }
    109 void init(int *ff){
    110     for(int i=2;i<=n;i++) fa[i]=ff[i];
    111 }
    112 };
    113 
    114 int fa[N1],son[N1],sz[N1],tp[N1],dep[N1];
    115 int st[N1],ed[N1],id[N1],tot;
    116 void dfs1(int u,int ff)
    117 {
    118     for(int j=E.head[u];j;j=E.nxt[j])
    119     {
    120         int v=E.to[j];
    121         if(v==ff) continue;
    122         dep[v]=dep[u]+1; dfs1(v,u); fa[v]=u;
    123         sz[u]+=sz[v]; son[u]=sz[v]>sz[son[u]]?v:son[u];
    124     }
    125     sz[u]++;
    126 }
    127 void dfs2(int u)
    128 {
    129     st[u]=ed[u]=++tot; id[tot]=u;
    130     if(son[u]) tp[son[u]]=tp[u], dfs2(son[u]), ed[u]=max(ed[u],ed[son[u]]);;
    131     for(int j=E.head[u];j;j=E.nxt[j])
    132     {
    133         int v=E.to[j];
    134         if(v==fa[u]||v==son[u]) continue;
    135         tp[v]=v; dfs2(v);
    136         ed[u]=max(ed[u],ed[v]);
    137     }
    138 }
    139 int lca(int x,int y)
    140 {
    141     while(tp[x]!=tp[y])
    142     {
    143         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
    144         x=fa[tp[x]];
    145     }
    146     return dep[x]<dep[y]?x:y;
    147 }
    148 void mksame(int x)
    149 {
    150     lct::access(x,st,ed);
    151 }
    152 int split(int x,int y)
    153 {
    154     int sx,sy,sf,f=lca(x,y);
    155     sx=s.query(st[x],st[x],1,n,1);
    156     sy=s.query(st[y],st[y],1,n,1);
    157     sf=s.query(st[f],st[f],1,n,1);
    158     return sx+sy-2*sf+1;
    159 }
    160 int qmax(int x){return s.query(st[x],ed[x],1,n,1);}
    161 void init()
    162 {
    163     dep[1]=1; dfs1(1,-1);
    164     tp[1]=1; dfs2(1);
    165     lct::init(fa);
    166     s.build(dep,id,1,n,1);
    167 }
    168 
    169 int qf(int x){return s.query(st[x],st[x],1,n,1);}
    170 
    171 int main()
    172 {
    173     scanf("%d%d",&n,&m);
    174     int i,j,fl,x,y,cnt=0,de; 
    175     for(i=1;i<n;i++) x=gint(), y=gint(), E.ae(x,y), E.ae(y,x);
    176     init();
    177     for(j=1;j<=m;j++)
    178     {
    179         fl=gint();
    180         if(fl==1){
    181             x=gint();
    182             mksame(x);
    183         }else if(fl==2){
    184             x=gint(); y=gint();
    185             printf("%d
    ",split(x,y));
    186         }else{
    187             x=gint();
    188             printf("%d
    ",qmax(x));
    189         }
    190     }
    191     return 0;
    192 }
  • 相关阅读:
    Spring Boot 的常用 API 说明
    错误:No WebApplicationContext found: no ContextLoaderListener or DispatcherServlet registered?
    [剑指offer] 2. 替换空格
    [剑指offer] 1. 二维数组中的的查找
    [leetcode] 300. Longest Increasing Subsequence (Medium)
    [leetcode] 929. Unique Email Addresses (easy)
    微信小程序post 服务端无法获得参数问题
    python虚拟环境管理 Pipenv 使用说明
    [leetcode] 87. Scramble String (Hard)
    [leetcode] 456. 132 Pattern (Medium)
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10162367.html
Copyright © 2011-2022 走看看