• 洛谷 P3258 [JLOI2014]松鼠的新家(树上差分)


    题目链接:https://www.luogu.com.cn/problem/P3258

    对点差分:

    sa[u]++;
    sa[v]++;
    sa[lca(u,v)]--;
    sa[f[lca(u,v)][0]]--;

    对边差分:

    sa[u]++;
    sa[v]++;
    sa[lca(u,v)]--;

    注意这道题a[2]~a[n],它们既被作为前一段的终点,同时也是下一段的起点,所以每个点差分后会被多算一次,需要减掉。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=3*1e5+5;
     7 int n,tot;
     8 int head[N],dep[N],f[N][30],a[N],sa[N];
     9 struct node{
    10     int to,next;
    11 }edge[N<<1];
    12 void init(){
    13     memset(head,-1,sizeof(head));
    14 }
    15 void add(int u,int v){
    16     edge[tot].to=v;
    17     edge[tot].next=head[u];
    18     head[u]=tot++;
    19 }
    20 void DFS(int u,int fa){
    21     f[u][0]=fa;
    22     dep[u]=dep[fa]+1;
    23     for(int i=1;(1<<i)<=dep[u];i++) f[u][i]=f[f[u][i-1]][i-1];
    24     for(int i=head[u];i!=-1;i=edge[i].next){
    25         int v=edge[i].to;
    26         if(v==fa) continue;
    27         DFS(v,u);
    28     }
    29 }
    30 int lca(int u,int v){
    31     if(dep[u]<dep[v]) swap(u,v);
    32     for(int i=20;i>=0;i--) if(dep[f[u][i]]>=dep[v]) u=f[u][i];
    33     if(u==v) return u;
    34     for(int i=20;i>=0;i--) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
    35     return f[u][0];
    36 }
    37 void get_sa(int u,int fa){
    38     for(int i=head[u];i!=-1;i=edge[i].next){
    39         int v=edge[i].to;
    40         if(v==fa) continue;
    41         get_sa(v,u);
    42         sa[u]+=sa[v];
    43     }
    44 }
    45 int main(){
    46     init();
    47     scanf("%d",&n);
    48     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    49     for(int i=1;i<n;i++){
    50         int x,y;
    51         scanf("%d%d",&x,&y);
    52         add(x,y); add(y,x);
    53     }
    54     DFS(1,0);
    55     for(int i=2;i<=n;i++){
    56         int u,v;
    57         u=a[i-1],v=a[i];
    58         sa[u]++;
    59         sa[v]++;
    60         int x=lca(u,v);
    61         sa[x]--;
    62         sa[f[x][0]]--;
    63     }
    64     get_sa(1,0);
    65     for(int i=2;i<=n;i++) sa[a[i]]--;
    66     for(int i=1;i<=n;i++) printf("%d
    ",sa[i]);
    67     return 0;
    68 }
    AC代码
  • 相关阅读:
    centos 下查找软件安装在哪里的命令
    Ubuntu常用命令大全
    linux下vi命令大全
    查看linux系统版本命令
    Linux系统安装时分区的选择(推荐)
    Java subList的使用
    Java中unicode增补字符(辅助平面)相关用法简介
    Java编码方式再学
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode 283. Move Zeroes
  • 原文地址:https://www.cnblogs.com/New-ljx/p/13443125.html
Copyright © 2020-2023  润新知