• [CF627D]Preorder Test


    题目大意:
      一个$n(nle2 imes10^5)$个结点的树,每个结点有一个权值$w_i$。可以任选一点为根,并选择一些结点交换其子结点的顺序,使得该树DFS序上第$m$个结点的权值最大。求最大权值。

    思路:
      二分答案$k$ ,树形DP检验可行性。
      对于以结点$x$为根的子树,用$f[x]$表示$x$的子树经过任意变换的所有DFS序中,满足$w_ige k$的最长前缀长度。
      若$w_x<k$,则$f[x]$显然为$0$。
      若$w_xge k$,则对于$x$的每个子结点$y$,若$f[y]=size[y]$,将$y$的子树插入到$x$子树DFS序的最前面仍然是合法的;而对于所有满足$f[y]<size[y]$的子结点$y$,可以选择一个$f[y]$最大的加入。考虑以$x$为根的情况,则只需要在$f[x]$上加上满足$f[y]<size[y]$的$f[y]$第二大的$f[y]$。此时不需要考虑加上的会是$x$上方的点,因为加上$x$上方的点的情况肯定能在$x$上方的点处统计到。
      时间复杂度$O(n)$。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 #include<forward_list>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=2e5+1;
    13 int w[N],f[N],k,size[N],ans,root;
    14 std::forward_list<int> e[N];
    15 inline void add_edge(const int &u,const int &v) {
    16     e[u].push_front(v);
    17     e[v].push_front(u);
    18 }
    19 void dfs(const int &x,const int &par) {
    20     f[x]=size[x]=1;
    21     int max1=0,max2=0;
    22     for(register auto &y:e[x]) {
    23         if(y==par) continue;
    24         dfs(y,x);
    25         size[x]+=size[y];
    26         if(f[y]==size[y]) {
    27             f[x]+=f[y];
    28         } else {
    29             if(f[y]>max1) std::swap(f[y],max1);
    30             if(f[y]>max2) std::swap(f[y],max2);
    31         }
    32     }
    33     f[x]=w[x]<k?0:f[x]+max1;
    34     ans=std::max(ans,f[x]+max2);
    35 }
    36 inline int calc() {
    37     dfs(root,ans=0);
    38     return ans;
    39 }
    40 int main() {
    41     const int n=getint(),m=getint();
    42     for(register int i=1;i<=n;i++) w[i]=getint();
    43     for(register int i=1;i<n;i++) {
    44         add_edge(getint(),getint());
    45     }
    46     root=std::min_element(&w[1],&w[n]+1)-w;
    47     int l=*std::min_element(&w[1],&w[n]+1);
    48     int r=*std::max_element(&w[1],&w[n]+1);
    49     while(l<=r) {
    50         k=(l+r)>>1;
    51         if(calc()>=m) {
    52             l=k+1;
    53         } else {
    54             r=k-1;
    55         }
    56     }
    57     printf("%d
    ",l-1);
    58     return 0;
    59 }
  • 相关阅读:
    maven-eclipse 中index.html页面乱码
    java-Unsupported major.minor version 52.0错误解决
    eclipse引入httpServlet源码
    eclipse恢复默认布局
    eclipse导入Java源码
    bootstrap fileinput api翻译笔记
    js判断display隐藏显示
    php根据路径获取文件名
    js事件处理-整理
    Jms(消息中间件)两种消息传输方式QUEUE和TOPIC比较
  • 原文地址:https://www.cnblogs.com/skylee03/p/8986814.html
Copyright © 2020-2023  润新知