zoukankan      html  css  js  c++  java
  • 【NOIP2016】天天爱跑步——LCA+树上差分

    题目链接

    真是一道神题(大家普遍认为是去年NOIP最难的一道so......),然而之前并没有写过关于树上差分的题目,所以自己想了一晚上+一早上都没能想出来(搞的心神不宁T^T)->还是太弱

    题解感觉没什么必要发了,网上的都差不多吧(都是nlogn的写法),需要的话可以看一下yy dalao的题解,还是蛮详细的-->戳这里

    听说能优化成O(n)的,有时间的话学一下吧感觉好神啊。

    //写完调了好久发现没建反向边/////捂脸

    //最近效率好低啊QAQ,NOIP要来了啊啊啊啊,刷题刷题~

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #include<algorithm>
     5 const int maxn=3e5+5;
     6 using namespace std;
     7 /*---------------------------------------------------------*/
     8 int n,m,tot=0;
     9 struct node{
    10     int next,to;
    11 }e[maxn*2];
    12 struct pos{int x,s;};
    13 int first[maxn],fa[maxn][22],w[maxn],deep[maxn],an[maxn],ans1[maxn],ans2[maxn<<1];
    14 bool ok[maxn];
    15 vector<pos>e1[maxn],e2[maxn<<1];
    16 int read()
    17 {
    18     int ans=0,f=1;char c=getchar();
    19     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    20     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    21     return ans*f;
    22 }
    23 /*------------------------------------------------------------*/
    24 void add(int x,int y)
    25 {
    26     tot++;e[tot].next=first[x];first[x]=tot;e[tot].to=y;
    27 }
    28 void dfs1(int x)
    29 {
    30     ok[x]=1;
    31     for(int i=1;(1<<i)<=deep[x];i++)
    32         fa[x][i]=fa[fa[x][i-1]][i-1];
    33     for(int i=first[x];i;i=e[i].next){
    34         int to=e[i].to;
    35         if(ok[to])continue;
    36         deep[to]=deep[x]+1;
    37         fa[to][0]=x;
    38         dfs1(to);
    39     }
    40 }
    41 int lca(int x,int y)
    42 {
    43     if(deep[x]>deep[y])swap(x,y);
    44     int d=deep[y]-deep[x];
    45     for(int i=0;(1<<i)<=d;i++)
    46         if((1<<i)&d)y=fa[y][i];
    47     if(x==y)return x;
    48     for(int i=20;i>=0;i--){
    49         if((1<<i)>deep[x]||(1<<i)>deep[y]||fa[x][i]==fa[y][i])continue;
    50         x=fa[x][i];y=fa[y][i];
    51     }
    52     return fa[x][0];
    53 }
    54 void dfs2(int x)
    55 {
    56     an[x]-=ans1[deep[x]+w[x]];
    57     an[x]-=ans2[w[x]-deep[x]+n];
    58     for(int i=0;i<e1[x].size();i++)ans1[e1[x][i].x]+=e1[x][i].s;
    59     for(int i=0;i<e2[x].size();i++)ans2[e2[x][i].x+n]+=e2[x][i].s;
    60     for(int i=first[x];i;i=e[i].next){
    61         int to=e[i].to;
    62         if(to==fa[x][0])continue;
    63         dfs2(to);
    64     }
    65     an[x]+=ans1[w[x]+deep[x]]+ans2[w[x]-deep[x]+n];
    66 }
    67 int main()
    68 {
    69     int u,v,si,ti;
    70     n=read();m=read();
    71     for(int i=1;i<=n-1;i++){
    72         u=read();v=read();
    73         add(u,v);add(v,u);
    74     }
    75     for(int i=1;i<=n;i++)w[i]=read();
    76     deep[1]=1;
    77     dfs1(1);
    78     for(int i=1;i<=m;i++){
    79         si=read();ti=read();
    80         int gr=lca(si,ti);
    81         e1[si].push_back((pos){deep[si],1});
    82         e1[gr].push_back((pos){deep[si],-1});
    83         e2[ti].push_back((pos){deep[si]-(deep[gr]<<1),1});
    84         e2[fa[gr][0]].push_back((pos){deep[si]-(deep[gr]<<1),-1});
    85     }
    86     dfs2(1);
    87     for(int i=1;i<=n-1;i++)
    88         printf("%d ",an[i]);
    89     printf("%d",an[n]);
    90     return 0;
    91 }
    NOIP2016 D1 T2
  • 相关阅读:
    多态实现--虚函数与纯虚函数
    CentOS6编译安装gcc高版本
    Linux多进程CS服务器简单测试
    Linux单用户CS模型TCP通讯完全注释手册
    进程线程及其状态
    Java学习-字符串、字符、ASCII、数字的互相转换
    Java学习-素数
    Java学习-日期
    Java学习-多态
    Java学习-练习
  • 原文地址:https://www.cnblogs.com/JKAI/p/7455333.html
Copyright © 2011-2022 走看看