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

    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

    正解:$link-cut tree$+树链剖分+线段树。

    这道题很巧妙啊。。利用$LCT$的神奇性质完美地解决了询问$1$的棘手操作。

    首先我们注意到,询问$1$其实就是$LCT$中的$access$操作。我们可以直接维护每个点到根节点的权值,然后利用$access$操作来处理这个问题。

    我们在$access$操作的时候,直接将当前点原来的实儿子所在的子树权值$+1$,当前待接上的实儿子所在子树权值$-1$,就能完美地处理这个操作了。注意,这里指的实儿子一定是在原树中深度最浅的点。我比较偷懒,就直接暴力找$splay$中深度最小的点。具体解释的话,画个图就能理解了,看下代码应该能弄懂吧。。

    对于询问$2$,我们可以发现,路径上的权值就是$val[x]+val[y]-2*val[lca(x,y)]+1$。这个式子是很好画图证明的。

    首先,$lca$的两个儿子颜色是不可能相同的,所以我们分两种情况讨论一下,一种是$lca$和其中一个儿子颜色相同,一种是$lca$和两个儿子颜色都不同。这样我们就能很容易地得出上述结论。

    对于询问$3$,我们直接区间查询,询问子树中的权值最大值就行了。

    以上操作,维护权值都是用线段树,求$lca$写树链剖分比较方便。然后我们就能$AC$此题了,虽然复杂度还是很玄学。。

    第一次$bzoj rank1$。。

      1 //It is made by wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <complex>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <cstdio>
      8 #include <vector>
      9 #include <cmath>
     10 #include <queue>
     11 #include <stack>
     12 #include <map>
     13 #include <set>
     14 #define inf (1<<30)
     15 #define N (100010)
     16 #define ls (x<<1)
     17 #define rs (x<<1|1)
     18 #define il inline
     19 #define RG register
     20 #define ll long long
     21 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     22 
     23 using namespace std;
     24 
     25 struct edge{ int nt,to; }g[2*N];
     26 
     27 int head[N],n,m,num;
     28 
     29 struct tree_cut{
     30     
     31     int top[N],fa[N],son[N],sz[N],dep[N],pos[N],tid[N],ed[N],cnt;
     32     
     33     il void dfs1(RG int x,RG int p){
     34     fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG int v;
     35     for (RG int i=head[x];i;i=g[i].nt){
     36         v=g[i].to; if (v==p) continue;
     37         dfs1(v,x),sz[x]+=sz[v];
     38         if (sz[son[x]]<=sz[v]) son[x]=v;
     39     }
     40     return;
     41     }
     42     
     43     il void dfs2(RG int x,RG int p,RG int anc){
     44     top[x]=anc,tid[x]=++cnt,pos[cnt]=x;
     45     if (son[x]) dfs2(son[x],x,anc); RG int v;
     46     for (RG int i=head[x];i;i=g[i].nt){
     47         v=g[i].to; if (v==p || v==son[x]) continue;
     48         dfs2(v,x,v);
     49     }
     50     ed[x]=cnt; return;
     51     }
     52     
     53     il int lca(RG int u,RG int v){
     54     while (top[u]!=top[v]){
     55         if (dep[top[u]]<dep[top[v]]) swap(u,v);
     56         u=fa[top[u]];
     57     }
     58     return dep[u]<dep[v] ? u : v;
     59     }
     60     
     61 }tree;
     62 
     63 struct segment_tree{
     64     
     65     int mx[4*N],lazy[4*N];
     66     
     67     il void pushdown(RG int x){
     68     mx[ls]+=lazy[x],mx[rs]+=lazy[x];
     69     lazy[ls]+=lazy[x],lazy[rs]+=lazy[x];
     70     lazy[x]=0; return;
     71     }
     72     
     73     il void build(RG int x,RG int l,RG int r){
     74     if (l==r){ mx[x]=tree.dep[tree.pos[l]]; return; }
     75     RG int mid=(l+r)>>1;
     76     build(ls,l,mid),build(rs,mid+1,r);
     77     mx[x]=max(mx[ls],mx[rs]); return;
     78     }
     79     
     80     il void update(RG int x,RG int l,RG int r,RG int xl,RG int xr,RG int v){
     81     if (xl<=l && r<=xr){ mx[x]+=v,lazy[x]+=v; return; }
     82     if (lazy[x]) pushdown(x); RG int mid=(l+r)>>1;
     83     if (xr<=mid) update(ls,l,mid,xl,xr,v);
     84     else if (xl>mid) update(rs,mid+1,r,xl,xr,v);
     85     else update(ls,l,mid,xl,mid,v),update(rs,mid+1,r,mid+1,xr,v);
     86     mx[x]=max(mx[ls],mx[rs]); return;
     87     }
     88     
     89     il int querymax(RG int x,RG int l,RG int r,RG int xl,RG int xr){
     90     if (xl<=l && r<=xr) return mx[x];
     91     if (lazy[x]) pushdown(x); RG int mid=(l+r)>>1;
     92     if (xr<=mid) return querymax(ls,l,mid,xl,xr);
     93     else if (xl>mid) return querymax(rs,mid+1,r,xl,xr);
     94     else return max(querymax(ls,l,mid,xl,mid),querymax(rs,mid+1,r,mid+1,xr));
     95     }
     96     
     97     il int ask(RG int x){ return querymax(1,1,n,tree.tid[x],tree.tid[x]); }
     98     
     99 }seg;
    100 
    101 struct link_cut_tree{
    102     
    103     int ch[N][2],fa[N];
    104     
    105     il int isroot(RG int x){
    106     return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
    107     }
    108     
    109     il void rotate(RG int x){
    110     RG int y=fa[x],z=fa[y],k=ch[y][0]==x;
    111     if (!isroot(y)) ch[z][ch[z][1]==y]=x;
    112     fa[x]=z,ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y;
    113     ch[x][k]=y,fa[y]=x; return;
    114     }
    115     
    116     il void splay(RG int x){
    117     while (!isroot(x)){
    118         RG int y=fa[x],z=fa[y];
    119         if (!isroot(y)){
    120         if ((ch[y][0]==x)^(ch[z][0]==y)) rotate(x);
    121         else rotate(y);
    122         }
    123         rotate(x);
    124     }
    125     return;
    126     }
    127     
    128     il void access(RG int x){
    129     RG int t=0;
    130     while (x){
    131         splay(x);
    132         if (ch[x][1]){
    133         RG int y=ch[x][1]; while (ch[y][0]) y=ch[y][0];
    134         seg.update(1,1,n,tree.tid[y],tree.ed[y],1);
    135         }
    136         if (t){
    137         RG int y=t; while (ch[y][0]) y=ch[y][0];
    138         seg.update(1,1,n,tree.tid[y],tree.ed[y],-1);
    139         }
    140         ch[x][1]=t,t=x,x=fa[x];
    141     }
    142     return;
    143     }
    144     
    145 }lct;
    146 
    147 il void insert(RG int from,RG int to){
    148     g[++num]=(edge){head[from],to},head[from]=num; return;
    149 }
    150 
    151 il int gi(){
    152     RG int x=0,q=1; RG char ch=getchar();
    153     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    154     if (ch=='-') q=-1,ch=getchar();
    155     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    156     return q*x;
    157 }
    158 
    159 il void work(){
    160     n=gi(),m=gi();
    161     for (RG int i=1,u,v;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u);
    162     tree.dfs1(1,0),tree.dfs2(1,0,1),seg.build(1,1,n);
    163     for (RG int i=2;i<=n;++i) lct.fa[i]=tree.fa[i];
    164     for (RG int i=1,type,x,y;i<=m;++i){
    165     type=gi(); if (type==1) x=gi(),lct.access(x);
    166     if (type==2){
    167         x=gi(),y=gi(); RG int Lca=tree.lca(x,y);
    168         printf("%d
    ",seg.ask(x)+seg.ask(y)-2*seg.ask(Lca)+1);
    169     }
    170     if (type==3) x=gi(),printf("%d
    ",seg.querymax(1,1,n,tree.tid[x],tree.ed[x]));
    171     }
    172     return;
    173 }
    174 
    175 int main(){
    176     File("paint");
    177     work();
    178     return 0;
    179 }
  • 相关阅读:
    hdu1915
    2014年9月28日 18:35:01
    洛谷—— P1122 最大子树和
    洛谷——P1103 书本整理
    洛谷—— P2049 魔术棋子
    UVA_1575
    洛谷—— P2424 约数和
    中文乱码问题
    JSP标签
    include指令
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6700710.html
Copyright © 2011-2022 走看看