• Codeforces 1009F Dominant Indices


    题面

    http://codeforces.com/contest/1009/problem/F

    题解

    启发式合并

    这是我做的第一道启发式合并题 感觉如果以前做过启发式合并的题的话 这题可以一眼秒掉

    就是个模板题吧

    唯一的问题就在于怎么从儿子更新到父亲

    我使用了一个map去记录

    但是如果用map会不会超时呢?

    启发式合并一个log+map一个log,1e6就过不去了

    但是这道题比较特殊 我们会发现 正常的启发式合并 每个点记录的信息是与子树大小线性相关

    但是这道题 记录的信息与子树深度线性相关

    据CF官方题解说 因为合并两个数组的时候 相当于destroy掉小的数组,是O(size of small array)的

    然后就证完了?(还是不能理解)

    启发式合并复杂度证明:

    算法的耗时来自于对查询的回答与各结点对cnt[]数组的操作。由于每次查询都是O(1)的,所以查询的总复杂度为O(m),可以忽略。考虑结点u对cnt[]数组的操作次数,设u的祖先从近到远依次为w_1,w_2,...,w_t。处理子树u时,结点u第一次对cnt[]数组进行操作,而结点u下一次对cnt[]数组进行操作,发生在u下一次不在某个祖先的儿子子树中最大的那棵中时,我们来说明这样的事只能发生O(lgn)次。若u不在w_k的儿子子树中最大的那棵中,则有size(w_k-1)*2≤size(w_k),由于size(w_t)=n,所以这样的事(u不在w_k的儿子子树中最大的那棵中)只能发生O(lgn)次。综上,各节点对cnt[]数组的操作次数为O(nlgn)。

    Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 
     5 ll read(){
     6     ll x=0,f=1;char c=getchar();
     7     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
     8     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
     9     return x*f;
    10 }
    11 
    12 const int maxn=1000100;
    13 int n;
    14 int head[maxn],to[maxn*2],nxt[maxn*2],cnt;
    15 map<int,int> m[maxn];
    16 int mx[maxn],son[maxn],dep[maxn];
    17 int ans[maxn];
    18 int mxd[maxn];
    19 
    20 void addedge(int a,int b){
    21     to[++cnt]=b,nxt[cnt]=head[a],head[a]=cnt;
    22     to[++cnt]=a,nxt[cnt]=head[b],head[b]=cnt;
    23 }
    24 
    25 void dfs1(int x,int fa=1){
    26     mx[x]=1;dep[x]=dep[fa]+1;
    27     for(int i=head[x];i;i=nxt[i]){
    28         int v=to[i];
    29         if(v==fa) continue;
    30         dfs1(v,x);
    31         mx[x]=max(mx[x],mx[v]+1);
    32         if(mx[v]>mx[son[x]]) son[x]=v;
    33     }
    34 }
    35 
    36 void dfs2(int x,int fa=1){
    37     for(int i=head[x];i;i=nxt[i]){
    38         int v=to[i];
    39         if(v==fa) continue;
    40         dfs2(v,x);
    41     }
    42     if(son[x]){
    43         swap(m[x],m[son[x]]);
    44         m[x][dep[x]]=1;
    45         mxd[x]=mxd[son[x]];
    46         ans[x]=ans[son[x]]+1;
    47         if(mxd[x]==1) ans[x]=0;
    48     }
    49     else{
    50         m[x][dep[x]]=1;
    51         mxd[x]=1;
    52         return;
    53     }
    54     for(int i=head[x];i;i=nxt[i]){
    55         int v=to[i];
    56         if(v==fa || v==son[x]) continue;
    57         for(map<int,int>::iterator it=m[v].begin();it!=m[v].end();it++){
    58             int k=it->first;
    59             m[x][k]+=(it->second);
    60             if(m[x][k]>mxd[x]){
    61                 mxd[x]=m[x][k];
    62                 ans[x]=k-dep[x];
    63             }
    64             if(m[x][k]==mxd[x]){
    65                 ans[x]=min(ans[x],k-dep[x]);
    66             }
    67         }
    68     }
    69 }
    70 
    71 int main(){
    72 #ifdef LZT
    73     freopen("in","r",stdin);
    74 #endif
    75     n=read();
    76     for(int i=1;i<n;i++){
    77         int x=read(),y=read();
    78         addedge(x,y);
    79     }
    80     dfs1(1);
    81     //for(int i=1;i<=n;i++)
    82     //    cout<<son[i]<<' '<<dep[i]<<endl;
    83     dfs2(1);
    84     for(int i=1;i<=n;i++)
    85         printf("%d
    ",ans[i]);
    86     return 0;
    87 }

    Review

    动机似乎非常显然。。。

  • 相关阅读:
    如何简单使用tensorboard展示(二)
    如何简单使用tensorboard展示(一)
    Cypress 系列之----03 常用API
    Cypress 系列之----02 自定义命令Custom Commands
    Windows下启动Jmeter出现Not able to find Java executable or version问题解决方案
    linux命令行下文件名中包含特殊符号如何的处理方法
    jenkins高级篇 pipeline系列之-—01简介
    Jenkins部署报错问题解决----git低版本引发的问题
    存储过程--使用变量循环调用
    jenkins高级篇 pipeline 系列之-—06 实现自动打增量包
  • 原文地址:https://www.cnblogs.com/wawawa8/p/9416579.html
Copyright © 2020-2023  润新知