zoukankan      html  css  js  c++  java
  • BZOJ4817: [Sdoi2017]树点涂色

    4817: [Sdoi2017]树点涂色

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 515  Solved: 302
    [Submit][Status][Discuss]

    Description

    Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路
    径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
    1 x:
    把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
    2 x y:
    求x到y的路径的权值。
    3 x y:
    在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
    Bob一共会进行m次操作

    Input

    第一行两个数n,m。
    接下来n-1行,每行两个数a,b,表示a与b之间有一条边。
    接下来m行,表示操作,格式见题目描述
    1<=n,m<=100000

    Output

    每当出现2,3操作,输出一行。
    如果是2操作,输出一个数表示路径的权值
    如果是3操作,输出一个数表示权值的最大值

    Sample Input

    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

    Sample Output

    3
    4
    2
    2
     
    思路{
      双倍经验题,同BZOJ3779
      具体来说的话查询路径间的权值就是拿$Ans_x+Ans_y-2*Ans_{lca}+1$。
      线段树大力搞一下就可以了。
    }
    #include<bits/stdc++.h>
    #define LL long long
    #define RG register
    #define il inline
    #define N 100010
    using namespace std;
    namespace tree{
    #define rs ((o<<1)|1)
    #define ls (o<<1)
    #define mid ((l+r)>>1)
        int Max[N*4],lazy[N*4];
        void down(int o){
    	if(lazy[o]){
    	    lazy[rs]+=lazy[o],lazy[ls]+=lazy[o];
    	    Max[rs]+=lazy[o],Max[ls]+=lazy[o];
    	    lazy[o]=0;
    	}
        }
        void modify(int o,int l,int r,int L,int R,int num){
    	if(l>=L&&r<=R){Max[o]+=num,lazy[o]+=num;return;}
    	down(o);
    	if(mid<L)modify(rs,mid+1,r,L,R,num);
    	else if(mid>=R)modify(ls,l,mid,L,R,num);
    	else modify(rs,mid+1,r,l,R,num),modify(ls,l,mid,L,R,num);
    	Max[o]=max(Max[rs],Max[ls]);
        }
        int query(int o,int l,int r,int L,int R){
    	if(l>=L&&r<=R)return Max[o];
    	down(o);
    	if(mid<L)return query(rs,mid+1,r,L,R);
    	else if(mid>=R)return query(ls,l,mid,L,R);
    	else return max(query(rs,mid+1,r,L,R),query(ls,l,mid,L,R));
        }
    }
    struct ed{int nxt,to;}e[N*2];
    int f[19][N],head[N],tot,dfn[N],til[N],id,n,q,fa[N],ch[N][2],dep[N],st[N];
    void link(int u,int v){e[tot].nxt=head[u];e[tot].to=v;head[u]=tot++;}
    void dfs(int u,int faa){fa[u]=faa;
        dep[u]=dep[faa]+1;dfn[u]=++id;tree::modify(1,1,n,dfn[u],dfn[u],dep[u]);
        f[0][u]=faa;for(int i=1;i<=18;++i)f[i][u]=f[i-1][f[i-1][u]];
        for(int i=head[u];i!=-1;i=e[i].nxt){
    	int v=e[i].to;if(v==faa)continue;
    	dfs(v,u);
        }til[u]=id;
    }
    int lca(int x,int y){
        if(dep[x]<dep[y])swap(x,y);int de=dep[x]-dep[y];
        for(int i=0;i<=18;++i)if((1<<i)&de)x=f[i][x];
        if(x!=y){
    	for(int i=18;i!=-1;i--)if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
    	x=f[0][x];
        }return x;
    }
    bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    void Rotate(int x){
        int y=fa[x],z=fa[y];
        int l=(ch[y][1]==x),r=l^1;
        if(!isroot(y))ch[z][ch[z][1]==y]=x;
        ch[y][l]=ch[x][r];fa[ch[x][r]]=y;
        ch[x][r]=y;fa[x]=z,fa[y]=x;
    }
    void Splay(int x){
        int y(x),z;
        while(!isroot(x)){
    	y=fa[x],z=fa[y];
    	if(!isroot(y)){
    	    if(ch[z][0]==y^ch[y][0]==x)Rotate(x);
    	    else Rotate(y);
    	}Rotate(x);
        }
    }
    int find(int x){
        while(ch[x][0])x=ch[x][0];
        return x;
    }
    void access(int x){
        int t(0);
        while(x){
    	Splay(x);
    	if(t){
    	    int u=find(t);
    	    tree::modify(1,1,n,dfn[u],til[u],-1);
    	}
    	if(ch[x][1]){
    	    int u=find(ch[x][1]);
    	    tree::modify(1,1,n,dfn[u],til[u],1);
    	}
    	ch[x][1]=t,t=x,x=fa[x];
        }
    }
    int main(){
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      memset(head,-1,sizeof(head));
      scanf("%d%d",&n,&q);
      for(int i=1;i<n;++i){int u,v;scanf("%d%d",&u,&v),link(u,v),link(v,u);}
      dfs(1,1);int flag,x,y;fa[1]=0;
      using namespace tree;
      for(int i=1;i<=q;++i){
          scanf("%d%d",&flag,&x);
          if(flag==1)access(x);
          if(flag==2){
    	  scanf("%d",&y);int Lca=lca(x,y);
    	  printf("%d
    ",query(1,1,n,dfn[x],dfn[x])+query(1,1,n,dfn[y],dfn[y])-
    		 2*query(1,1,n,dfn[Lca],dfn[Lca])+1);
          }
          if(flag==3)printf("%d
    ",query(1,1,n,dfn[x],til[x]));
      }return 0;
    }
    
  • 相关阅读:
    LeetCode15 3Sum
    LeetCode10 Regular Expression Matching
    LeetCode20 Valid Parentheses
    LeetCode21 Merge Two Sorted Lists
    LeetCode13 Roman to Integer
    LeetCode12 Integer to Roman
    LeetCode11 Container With Most Water
    LeetCode19 Remove Nth Node From End of List
    LeetCode14 Longest Common Prefix
    LeetCode9 Palindrome Number
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7838380.html
Copyright © 2011-2022 走看看