zoukankan      html  css  js  c++  java
  • [atAGC007E]Shik and Travel

    二分枚举答案,判定答案是否合法

    贪心:每一个叶子只能经过一遍,因此叶子的顺序一定是一个dfs序,即走完一棵子树中的所有叶子才会到子树外

    根据这个贪心可以dp,设$f[k][l][r]$表示仅考虑$k$的子树,$l$和$r$为第一个和最后一个叶子到根的距离,时间复杂度大约有$o(n^{4或5})$,无法通过

    考虑优化,将所有$f[k][l][r]=1$的$(l,r)$记录下来,若存在$l'le l$且$r'le r$,$(l,r)$一定没有意义,这可以用一个单调栈来维护,那么同一个$l/r$所对应的$r/l$最多只有1个

    转移考虑合并,不妨假设左子树比右子树小,枚举左子树中的$(l_{1},r_{1})$,对于右子树中的$(l_{2},r_{2})$,有两种转移的可能:1.若$r_{1}+l_{2}+v_{ls}+v_{rs}le ans$,转移到$(l_{1}+v_{ls},r_{2}+v_{rs})$;2.若$l_{1}+r_{2}+v_{ls}+v_{rs}le ans$,转移到$(l_{2}+v_{rs},r_{1}+v_{ls})$

    可以利用单调性来优化,即找到满足$l_{2}le ans-r_{1}-v_{ls}-v_{rs}$且$r_{2}$最小的位置(第一种转移),那么每一组$(l_{1},r_{1})$最多转移到$k$中的两个状态(反之同理),即有$|state[k]|le 2min(|state[ls]|,|state[rs]|)$,空间复杂度为$o(nlog_{2}n)$,时间复杂度即为空间复杂度乘上二分,为$o(nlog^{ 2}_{2}n)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200005
     4 #define ll long long
     5 #define fi first
     6 #define se second
     7 vector<pair<ll,ll> >v,f[N];
     8 int n,x,ls[N],rs[N],w[N];
     9 ll ans;
    10 void dfs(int k){
    11     f[k].clear();
    12     if ((!ls[k])&&(!rs[k])){
    13         f[k].push_back(make_pair(0,0));
    14         return;
    15     }
    16     dfs(ls[k]);
    17     dfs(rs[k]);
    18     ll s=ans-w[ls[k]]-w[rs[k]];
    19     for(int i=0,j=0;i<f[ls[k]].size();i++){
    20         while ((j<f[rs[k]].size())&&(f[rs[k]][j].fi<=s-f[ls[k]][i].se))j++;
    21         if ((j)&&(f[rs[k]][j-1].fi<=s-f[ls[k]][i].se))f[k].push_back(make_pair(f[ls[k]][i].fi+w[ls[k]],f[rs[k]][j-1].se+w[rs[k]]));
    22     }
    23     swap(ls[k],rs[k]);
    24     for(int i=0,j=0;i<f[ls[k]].size();i++){
    25         while ((j<f[rs[k]].size())&&(f[rs[k]][j].fi<=s-f[ls[k]][i].se))j++;
    26         if ((j)&&(f[rs[k]][j-1].fi<=s-f[ls[k]][i].se))f[k].push_back(make_pair(f[ls[k]][i].fi+w[ls[k]],f[rs[k]][j-1].se+w[rs[k]]));
    27     }
    28     if (!f[k].size())return;
    29     sort(f[k].begin(),f[k].end());
    30     v.clear();
    31     v.push_back(f[k][0]);
    32     for(int i=1;i<f[k].size();i++)
    33         if (f[k][i].se<v[(int)v.size()-1].se)v.push_back(f[k][i]);
    34     f[k]=v;
    35 }
    36 bool pd(ll k){
    37     ans=k;
    38     dfs(1);
    39     return f[1].size();
    40 }
    41 int main(){
    42     scanf("%d",&n);
    43     for(int i=2;i<=n;i++){
    44         scanf("%d%d",&x,&w[i]);
    45         if (!ls[x])ls[x]=i;
    46         else rs[x]=i;
    47     }
    48     ll l=0,r=1LL*N*N;
    49     while (l<r){
    50         ll mid=(l+r>>1);
    51         if (pd(mid))r=mid;
    52         else l=mid+1;
    53     }
    54     printf("%lld",l);
    55 } 
    View Code
  • 相关阅读:
    Effective Java 19 Use interfaces only to define types
    Effective Java 18 Prefer interfaces to abstract classes
    Effective Java 17 Design and document for inheritance or else prohibit it
    Effective Java 16 Favor composition over inheritance
    Effective Java 15 Minimize mutability
    Effective Java 14 In public classes, use accessor methods, not public fields
    Effective Java 13 Minimize the accessibility of classes and members
    Effective Java 12 Consider implementing Comparable
    sencha touch SortableList 的使用
    sencha touch dataview 中添加 button 等复杂布局并添加监听事件
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13820763.html
Copyright © 2011-2022 走看看