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

    传送门

    吐槽一波怎么今年的山东OI这么水……(B

    不难看出第一种操作就是LCT的access,那么每个点到根节点的颜色种数就是虚边数量+1,两点间颜色种数同理……

    第三种操作可以用把每个虚边挂着的点的子树权值全部+1的方式来维护,那么直接LCT+区间修改区间求max的线段树维护即可,复杂度$O(nlog^2 n)$。

      1 /**************************************************************
      2     Problem: 4817
      3     User: _Angel_
      4     Language: C++
      5     Result: Accepted
      6     Time:5500 ms
      7     Memory:21092 kb
      8 ****************************************************************/
      9 #include<cstdio>
     10 #include<cstring>
     11 #include<algorithm>
     12 #include<vector>
     13 #define isroot(x) ((x)->p==null||((x)!=(x)->p->ch[0]&&(x)!=(x)->p->ch[1]))
     14 #define dir(x) ((x)==(x)->p->ch[1])
     15 using namespace std;
     16 const int maxn=100010;
     17 struct node{node *ch[2],*p;}null[maxn];
     18 void dfs(int);
     19 int LCA(int,int);
     20 node *access(node*);
     21 node *getroot(node*);
     22 void splay(node*);
     23 void rot(node*,int);
     24 void modify(int,int,int);
     25 int query(int,int,int);
     26 int mx[maxn<<2]={0},lazy[maxn<<2]={0};
     27 vector<int>G[maxn];
     28 int f[maxn][20],d[maxn],dfn[maxn],finish[maxn],tim=0;
     29 int n,m,lgn=0,s,t,k,x,y;
     30 int main(){
     31     null->ch[0]=null->ch[1]=null->p=null;
     32     scanf("%d%d",&n,&m);
     33     for(int i=1;i<=n;i++)null[i].ch[0]=null[i].ch[1]=null[i].p=null;
     34     for(int i=1;i<n;i++){
     35         scanf("%d%d",&x,&y);
     36         G[x].push_back(y);
     37         G[y].push_back(x);
     38     }
     39     dfs(1);
     40     for(int j=1;j<=lgn;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
     41     while(m--){
     42         scanf("%d%d",&k,&x);
     43         if(k==1)access(null+x);
     44         else if(k==2){
     45             scanf("%d",&y);
     46             s=t=dfn[x];
     47             int ans=query(1,n,1);
     48             s=t=dfn[y];
     49             ans+=query(1,n,1);
     50             s=t=dfn[LCA(x,y)];
     51             ans-=query(1,n,1)<<1;
     52             printf("%d
    ",ans+1);
     53         }
     54         else if(k==3){
     55             s=dfn[x];
     56             t=finish[x];
     57             printf("%d
    ",query(1,n,1)+1);
     58         }
     59     }
     60     return 0;
     61 }
     62 void dfs(int x){
     63     dfn[x]=++tim;
     64     d[x]=d[f[x][0]]+1;
     65     null[x].p=null+f[x][0];
     66     while((1<<lgn)<d[x])lgn++;
     67     for(int i=0;i<(int)G[x].size();i++)if(G[x][i]!=f[x][0]){
     68         f[G[x][i]][0]=x;
     69         dfs(G[x][i]);
     70     }
     71     finish[x]=tim;
     72     if(f[x][0]){
     73         s=dfn[x];
     74         t=finish[x];
     75         k=1;
     76         modify(1,n,1);
     77     }
     78 }
     79 int LCA(int x,int y){
     80     if(d[x]!=d[y]){
     81         if(d[x]<d[y])swap(x,y);
     82         for(int i=lgn;i>=0;i--)if(d[f[x][i]]>=d[y])x=f[x][i];
     83     }
     84     if(x==y)return x;
     85     for(int i=lgn;i>=0;i--)if(f[x][i]!=f[y][i]){
     86         x=f[x][i];
     87         y=f[y][i];
     88     }
     89     return f[x][0];
     90 }
     91 node *access(node *x){
     92     node *y=null;
     93     while(x!=null){
     94         splay(x);
     95         if(x->ch[1]!=null){
     96             node *u=x->ch[1];
     97             x->ch[1]=null;
     98             u=getroot(u);
     99             s=dfn[u-null];
    100             t=finish[u-null];
    101             k=1;
    102             modify(1,n,1);
    103         }
    104         if(y!=null){
    105             y=getroot(y);
    106             s=dfn[y-null];
    107             t=finish[y-null];
    108             k=-1;
    109             modify(1,n,1);
    110         }
    111         x->ch[1]=y;
    112         y=x;
    113         x=x->p;
    114     }
    115     return y;
    116 }
    117 node *getroot(node *x){
    118     splay(x);
    119     while(x->ch[0]!=null)x=x->ch[0];
    120     splay(x);
    121     return x;
    122 }
    123 void splay(node *x){
    124     while(!isroot(x)){
    125         if(isroot(x->p)){
    126             rot(x->p,dir(x)^1);
    127             break;
    128         }
    129         if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1);
    130         else rot(x->p,dir(x)^1);
    131         rot(x->p,dir(x)^1);
    132     }
    133 }
    134 inline void rot(node *x,int d){
    135     node *y=x->ch[d^1];
    136     if((x->ch[d^1]=y->ch[d])!=null)y->ch[d]->p=x;
    137     y->p=x->p;
    138     if(!isroot(x))x->p->ch[dir(x)]=y;
    139     (y->ch[d]=x)->p=y;
    140 }
    141 void modify(int l,int r,int rt){
    142     if(s<=l&&t>=r){
    143         mx[rt]+=k;
    144         lazy[rt]+=k;
    145         return;
    146     }
    147     int mid=(l+r)>>1;
    148     if(s<=mid)modify(l,mid,rt<<1);
    149     if(t>mid)modify(mid+1,r,rt<<1|1);
    150     mx[rt]=max(mx[rt<<1],mx[rt<<1|1])+lazy[rt];
    151 }
    152 int query(int l,int r,int rt){
    153     if(s<=l&&t>=r)return mx[rt];
    154     int mid=(l+r)>>1,ans=0;
    155     if(s<=mid)ans=max(ans,query(l,mid,rt<<1));
    156     if(t>mid)ans=max(ans,query(mid+1,r,rt<<1|1));
    157     return ans+lazy[rt];
    158 }
    View Code

    ps:如果没记错的话,这题应该是重组病毒那题的超级弱化版……

  • 相关阅读:
    Redis5设计与源码分析 (第17章 HyperLogLog相关命令的实现)
    Redis5设计与源码分析 (第16章 GEO相关命令)
    ES5和ES6函数的this指向
    vue响应式原理 (响应式并不等于数据双向绑定,千万不要混淆)
    vue中data为什么是函数而不是对象
    vue-enum 前端常量 枚举工具
    Vue3 写业务逻辑不适合用TS(TypeScript)
    vue-property-decorator vue3 ts 用的装饰器
    github git clone下载加速 && npm install 下载加速
    vue3 如果用ts,导出时候要用 defineComponent,这俩是配对的,为了类型的审查正确
  • 原文地址:https://www.cnblogs.com/hzoier/p/6697963.html
Copyright © 2011-2022 走看看