• SDOI2017 树点涂色——LCT the END


    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

            --by BZOJ

    http://www.lydsy.com/JudgeOnline/problem.php?id=4817



    大概自己也没想到会回来写这道题吧。

    一直对之前见到的,没做出来的题挺抵触的,

    不过这是不对的,

    题做不出来,也正常,

    谁还能把所有的题全做出来呢,

    况且,我见到这个题时还不会LCT,

    我当时已经打出了树链剖分做法的全部了,

    当然爆了一两个点的栈,SD的省选嘛,

    然而自己弱是不应该找理由的,

    题做不出来就是弱,

    没理由的,

    那就不应该逃避了,

    那么,如果我没有死,你们都将看到我;



    如果用LCT记录颜色个数的话,会非常僵,大概只能解决树链剖分解决的问题,

    也就是操作三之外的;

    但在观察每一个时期树上的颜色情况,发现与LCT的结构类似;

    于是考虑利用LCT的结构维护颜色;

    对于一二操作;

    一就是从某点ACCESS;

    二就是从某点空跑ACCESS而不改变splay的组成;

    考虑一对三的影响:

    发现在ACCESS连接两个点时,父方的点的原儿子的子树到根的颜色数+1,儿子方的点自己的子树颜色树减一;

    维护线段树即可;

    代码:

      1 #include<cstdio>
      2 using namespace std;
      3 int max[400010],mark[400010],rank[100010],dep[100010],size[100010],a[100010];
      4 struct dt{
      5     int fa,ch[2];
      6 }data[100010];
      7 struct ss{
      8     int to,next;
      9 }e[200010];
     10 int first[100010],num;
     11 int n,m;
     12 void build(int ,int );
     13 void dfs(int ,int ,int );
     14 void builine(int ,int ,int );
     15 void access(int );
     16 int find_top(int );
     17 void splay(int );
     18 void roll(int );
     19 void find(int ,int );
     20 void add(int ,int ,int ,int ,int ,int );
     21 int ans(int ,int ,int ,int ,int );
     22 void down(int );
     23 inline void in(int &ans)
     24 {
     25     ans=0;bool p=false;char ch=getchar();
     26     while((ch>'9' || ch<'0')&&ch!='-') ch=getchar();
     27     if(ch=='-') p=true,ch=getchar();
     28     while(ch<='9'&&ch>='0') ans=ans*10+ch-'0',ch=getchar();
     29     if(p) ans=-ans;
     30 }
     31 int main()
     32 {
     33     int i,j,k,x,y;
     34     in(n),in(m);
     35     for(i=1;i<=n-1;i++){
     36         in(j),in(k);
     37         build(j,k);build(k,j);
     38     }
     39     num=0;dfs(1,1,0);
     40     num=0;builine(1,n,1);
     41     for(i=1;i<=m;i++){
     42         in(j);
     43         if(j==1){
     44             in(x);
     45             access(x);
     46         }
     47         if(j==2){
     48             in(x),in(y);
     49             find(x,y);
     50         }
     51         if(j==3){
     52             in(x);
     53             y=ans(1,n,1,rank[x],rank[x]+size[x]-1);
     54             printf("%d
    ",y);
     55         }
     56     }
     57     return 0;
     58 }
     59 void build(int f,int t){
     60     e[++num].next=first[f];
     61     e[num].to=t;
     62     first[f]=num;
     63 }
     64 void dfs(int now,int d,int fa){
     65     int i;
     66     dep[now]=d;size[now]=1;rank[now]=++num;a[num]=now;data[now].fa=fa;
     67     for(i=first[now];i;i=e[i].next)
     68         if(e[i].to!=fa){
     69             dfs(e[i].to,d+1,now);
     70             size[now]+=size[e[i].to];
     71         }
     72 }
     73 void builine(int l,int r,int nu){
     74     if(l==r){
     75         max[nu]=dep[a[++num]];
     76         return ;
     77     }
     78     int mid=(l+r)>>1;
     79     builine(l,mid,nu<<1);
     80     builine(mid+1,r,nu<<1|1);
     81     max[nu]=max[nu<<1]>max[nu<<1|1]?max[nu<<1]:max[nu<<1|1];
     82 }
     83 void access(int x){
     84     int y=0,z;
     85     while(x){
     86         splay(x);z=find_top(y);
     87         if(z)add(1,n,1,rank[z],rank[z]+size[z]-1,-1);
     88         z=data[x].ch[1];
     89         data[x].ch[1]=y;
     90         y=x;x=data[x].fa;
     91         z=find_top(z);
     92         if(z)add(1,n,1,rank[z],rank[z]+size[z]-1,1);
     93     }
     94 }
     95 int find_top(int x){
     96     splay(x);
     97     while(data[x].ch[0])
     98         x=data[x].ch[0];
     99     return x;
    100 }
    101 void splay(int x){
    102     if(!x)return ;
    103     int fa,fafa;
    104     fa=data[x].fa;fafa=data[fa].fa;
    105     for(;data[fa].ch[0]==x||data[fa].ch[1]==x;roll(x),fa=data[x].fa,fafa=data[fa].fa){
    106         if(data[fafa].ch[0]==fa||data[fafa].ch[1]==fa){
    107             if((data[fafa].ch[1]==fa)^(data[fa].ch[1]==x))
    108                 roll(x);
    109             else
    110                 roll(fa);
    111         }
    112     }
    113 }
    114 void roll(int now){
    115     int fa=data[now].fa,fafa=data[fa].fa,wh=data[fa].ch[1]==now;
    116     data[fa].ch[wh]=data[now].ch[wh^1];data[data[fa].ch[wh]].fa=fa;
    117     data[now].ch[wh^1]=fa;data[fa].fa=now;
    118     data[now].fa=fafa;
    119     if (data[fafa].ch[0]==fa||data[fafa].ch[1]==fa)
    120         data[fafa].ch[data[fafa].ch[1]==fa]=now;
    121 }
    122 void find(int x,int y){
    123     int ans=1;
    124     x=find_top(x);y=find_top(y);
    125     while(x!=y){
    126         if(dep[x]>dep[y]){
    127             splay(x);x=find_top(data[x].fa);ans++;
    128         }
    129         else{
    130             splay(y);y=find_top(data[y].fa);ans++;
    131         }
    132     }
    133     printf("%d
    ",ans);
    134 }
    135 void add(int l,int r,int nu,int L,int R,int x){
    136     if(L<=l&&r<=R){
    137         max[nu]+=x;
    138         mark[nu]+=x;
    139         return ;
    140     }
    141     int mid=(l+r)>>1;
    142     down(nu);
    143     if(L<=mid)
    144         add(l,mid,nu<<1,L,R,x);
    145     if(R>mid)
    146         add(mid+1,r,nu<<1|1,L,R,x);
    147     max[nu]=max[nu<<1]>max[nu<<1|1]?max[nu<<1]:max[nu<<1|1];
    148 }
    149 int ans(int l,int r,int nu,int L,int R){
    150     if(L<=l&&r<=R)
    151         return max[nu];
    152     int mid=(l+r)>>1,lm=0,rm=0;
    153     down(nu);
    154     if(L<=mid)
    155         lm=ans(l,mid,nu<<1,L,R);
    156     if(R>mid)
    157         rm=ans(mid+1,r,nu<<1|1,L,R);
    158     if(lm>rm)return lm;
    159     return rm;
    160 }
    161 void down(int nu){
    162     if(!mark[nu])return;
    163     max[nu<<1]+=mark[nu];max[nu<<1|1]+=mark[nu];
    164     mark[nu<<1]+=mark[nu];mark[nu<<1|1]+=mark[nu];
    165     mark[nu]=0;
    166 }
  • 相关阅读:
    【随笔浅谈】splay 时间复杂度简要分析
    【Luogu P4406】「CQOI2005」三角形面积并
    LLVM12.0.1,编译
    electrion 为了便于调试,打开控制台
    MySQL插入大量数据探讨
    【Django前后端部署】更新部署,不使用反向代理
    检测两台服务器某个目录下的文件一致性
    ceph-rbd和cephfs使用
    Laravel
    Scrcpy投屏神器--让你的电脑流畅操作手机
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/7100638.html
Copyright © 2020-2023  润新知