zoukankan      html  css  js  c++  java
  • [SDOI2017]树点涂色

    题目描述

    Bob有一棵nn个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。

    定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。

    Bob可能会进行这几种操作:

    • 1 x

    把点xx到根节点的路径上所有的点染上一种没有用过的新颜色。

    • 2 x y

    xx到yy的路径的权值。

    • 3 x

    在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。

    Bob一共会进行mm次操作

    输入输出格式

    输入格式:

    第一行两个数n,mn,m。

    接下来n-1n1行,每行两个数a,ba,b,表示aa与bb之间有一条边。

    接下来mm行,表示操作,格式见题目描述

    输出格式:

    每当出现2,3操作,输出一行。

    如果是2操作,输出一个数表示路径的权值

    如果是3操作,输出一个数表示权值的最大值

    输入输出样例

    输入样例#1:
    5 6
    1 2
    2 3
    3 4
    3 5
    2 4 5
    3 3
    1 4
    2 4 5
    1 5
    2 4 5
    输出样例#1:
    3
    4
    2
    2

    说明

    共10个测试点

    测试点1,1leq n,mleq10001n,m1000

    测试点2、3,没有2操作

    测试点4、5,没有3操作

    测试点6,树的生成方式是,对于i(2leq i leq n)i(2in),在1到i-1i1中随机选一个点作为i的父节点。

    测试点7,1leq n,mleq 500001n,m50000

    测试点8,1leq n leq 500001n50000

    测试点9,10,无特殊限制

    对所有数据,1leq n leq 10^51n105​​,1leq m leq 10^51m105​​

    时间限制:1s

    空间限制:128MB

    维护一个LCT,每个Splay里都是颜色相同的点.那么操作2的答案就是这两个点路径上的虚边的数量+1.

    操作3的答案就是子树中每个点到根的路径虚边最大值+1.因为每次操作1都会用一种新的颜色,那么2的答案=f[x]+f[y]-2*f[lca(x,y)]+1.f[x]代表x到根的路径上的虚边数量.
    然后这个东西显然树链剖分用线段树来维护,顺便求出lca.那么操作2为单点查询,操作3为区间查询(dfn).
    然后再考虑操作1对查询的影响.
    LCT中的access操作,每次将一条实边变成虚边的时候,将这颗子树中的值全部加1,虚边变实边相反.

    这里有一个细节没有考虑到,因为这条路径是用Splay存的,那么原树上与这条要修改的边相连的点并不是Splay中与这条边相连的那个点.

    所以区间修改时要找最浅的那个点,即为Splay中那颗子树的最左边的点.
      1 #include<bits/stdc++.h>
      2 #define ls o*2
      3 #define rs o*2+1
      4 #define pre t[x].fa
      5 #define LS t[x].ch[0]
      6 #define RS t[x].ch[1]
      7 #define maxn 100010
      8 #define RG register
      9 using namespace std;
     10 struct Edge{
     11   int nex,to;
     12 }e[maxn*2];
     13 struct lct{int w,ch[2],fa;}t[maxn];
     14 int head[maxn],edge=0,top[maxn],dfn[maxn],dfp[maxn],dad[maxn],ed[maxn],deep[maxn],son[maxn],size[maxn];
     15 int n,b[maxn*4],lazy[maxn*4];
     16 inline void add(int from,int to){
     17   e[++edge].nex=head[from];
     18   e[edge].to=to;
     19   head[from]=edge;
     20 }
     21 void dfs1(int x,int fa){
     22   size[x]=1;
     23   for(RG int i=head[x];i;i=e[i].nex){
     24     int v=e[i].to;
     25     if(v==fa) continue;
     26     deep[v]=deep[x]+1;
     27     dad[v]=x;t[v].fa=x;
     28     dfs1(v,x);
     29     size[x]+=size[v];
     30     if(size[v]>size[son[x]])son[x]=v;
     31   }
     32 }
     33 int de=0;
     34 void dfs2(int x,int fa){
     35   dfn[x]=++de;dfp[de]=x;
     36   if(son[x])top[son[x]]=top[x],dfs2(son[x],x);
     37   for(int i=head[x];i;i=e[i].nex){
     38     int v=e[i].to;
     39     if(v==fa || v==son[x])continue;
     40     top[v]=v;
     41     dfs2(v,x);
     42   }
     43   ed[x]=de;
     44 }
     45 void build(int o,int l,int r){
     46   if(l==r){b[o]=deep[dfp[l]];return;}
     47   int mid=(l+r)>>1;
     48   build(ls,l,mid);build(rs,mid+1,r);
     49   b[o]=max(b[ls],b[rs]);
     50 }
     51 inline void down(int o){
     52   if(lazy[o]){
     53     int k=lazy[o];lazy[o]=0;
     54     b[ls]+=k,b[rs]+=k,lazy[ls]+=k,lazy[rs]+=k;
     55   }
     56 }
     57 void change(int o,int l,int r,int u,int v,int w){
     58   if(l!=r) down(o);
     59   if(l>v || r<u) return;
     60   if(l>=u && r<=v){b[o]+=w,lazy[o]+=w;return;}
     61   int mid=(l+r)>>1;
     62   if(v<=mid) change(ls,l,mid,u,v,w);
     63   else if(u>mid) change(rs,mid+1,r,u,v,w);
     64   else change(ls,l,mid,u,mid,w),change(rs,mid+1,r,mid+1,v,w);
     65   b[o]=max(b[ls],b[rs]);
     66 }
     67 inline bool isrt(int x){return t[pre].ch[0]!=x && t[pre].ch[1]!=x;}
     68 inline bool Son(int x){return t[pre].ch[1]==x;}
     69 inline void Rotate(int x){
     70   int f=t[x].fa,g=t[f].fa,c=Son(x);
     71   if(!isrt(f)) t[g].ch[Son(f)]=x;
     72   t[x].fa=g;
     73   t[f].ch[c]=t[x].ch[c^1],t[t[f].ch[c]].fa=f;
     74   t[x].ch[c^1]=f,t[f].fa=x;
     75 }
     76 inline void Splay(int x){
     77   for(;!isrt(x);Rotate(x))
     78     if(!isrt(pre)) Rotate(Son(pre)==Son(x)?pre:x);
     79 }
     80 inline void access(int x){
     81   for(RG int y=0;x;y=x,x=pre){
     82     Splay(x);if(RS){
     83       int kp=RS;
     84       while(t[kp].ch[0])kp=t[kp].ch[0];
     85       change(1,1,n,dfn[kp],ed[kp],1);
     86     }
     87     RS=y;if(RS){
     88       int kp=RS;
     89       while(t[kp].ch[0])kp=t[kp].ch[0];
     90       change(1,1,n,dfn[kp],ed[kp],-1);
     91     }
     92   }
     93 }
     94 int Find(int o,int l,int r,int p){
     95   if(l!=r) down(o);
     96   if(l==r) return b[o];
     97   int mid=(l+r)>>1;
     98   if(p<=mid)return Find(ls,l,mid,p);
     99   else return Find(rs,mid+1,r,p);
    100 }
    101 int query(int o,int l,int r,int u,int v){
    102   if(l!=r) down(o);
    103   if(l>v || r<u) return 0;
    104   if(l>=u && r<=v) return b[o];
    105   int mid=(l+r)>>1;
    106   if(v<=mid) return query(ls,l,mid,u,v);
    107   else if(u>mid) return query(rs,mid+1,r,u,v);
    108   else return max(query(ls,l,mid,u,mid),query(rs,mid+1,r,mid+1,v));
    109 }
    110 inline void lca(int x,int y){
    111   int xx=x,yy=y,LCA;
    112   while(top[x]!=top[y]){
    113     if(deep[top[x]]>deep[top[y]])x=dad[top[x]];
    114     else y=dad[top[y]];
    115   }
    116   LCA=deep[x]>deep[y]?y:x;
    117   printf("%d
    ",Find(1,1,n,dfn[xx])+Find(1,1,n,dfn[yy])-2*Find(1,1,n,dfn[LCA])+1);
    118 }
    119 int main(){
    120   int m,type,x,y;
    121   scanf("%d%d",&n,&m);
    122   for(RG int i=1;i<n;i++)
    123     scanf("%d%d",&x,&y),add(x,y),add(y,x);
    124   top[1]=1;
    125   dfs1(1,0),dfs2(1,0);
    126   build(1,1,n);
    127   for(RG int i=1;i<=m;i++){
    128     scanf("%d",&type);
    129     if(type==1) scanf("%d",&x),access(x);
    130     if(type==2) scanf("%d%d",&x,&y),lca(x,y);
    131     if(type==3) scanf("%d",&x),printf("%d
    ",query(1,1,n,dfn[x],ed[x])+1);
    132   }
    133   return 0;
    134 }
    
    
    
     
  • 相关阅读:
    ActiveMQ介绍及安装
    Spring注解驱动开发
    Redis 安装、配置、集群
    FastDFS的使用
    How are you vs How are you doing
    阅微草堂笔记
    我在实习的英文表达
    INTRO: THE DAWN (亡灵序曲) 中独白
    银魂的武士道
    Linguistic Data Consortium (LDC)
  • 原文地址:https://www.cnblogs.com/pantakill/p/7282480.html
Copyright © 2011-2022 走看看