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 }
    
    
    
     
  • 相关阅读:
    67. Add Binary
    66. Plus One
    64. Minimum Path Sum
    63. Unique Paths II
    How to skip all the wizard pages and go directly to the installation process?
    Inno Setup打包之先卸载再安装
    How to change the header background color of a QTableView
    Openstack object list 一次最多有一万个 object
    Openstack 的 Log 在 /var/log/syslog 里 【Ubuntu】
    Git 分支
  • 原文地址:https://www.cnblogs.com/pantakill/p/7282480.html
Copyright © 2011-2022 走看看