zoukankan      html  css  js  c++  java
  • day50-时中

    T1 CF516D Drazil and Morning Exercise

    • 给定一棵 n 个点的树,边有边权。
    • 定义 (f_x = max_{i=1}^n ext{dist}(x,i))
    • q 次询问最大的满足 (max_{x in s} f_x - min_{x in s} f_x le l) 的连通块 s 包含的点数。
    • (n le 10^5,q le 50)

    solution

    首先,两边dfs求出对于每个点的 (f_x) ,然后考虑以直径的中点作为根,那么在这个新的树里面,父亲的(f) 就会$ le $ 儿子的(f) ,满足一种单调性,于是用类似双指针的东西维护一遍即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e5+10;
    #define int long long
    inline int read()
    {
       register int x = 0 , f = 0; register char c = getchar();
       while(c < '0' || c > '9') f |= c == '-' , c = getchar();
       while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48) , c = getchar();
       return f ? -x : x;
    }
    int n;
    int fa[N] , up[N] , f[N] , g[N] , p[N] , siz[N];
    struct node { int v , c; node(int v = 0 , int c = 0) : v(v) , c(c) {} };
    vector< node > G[N];
    
    void dfs1(int x , int Fa)
    {
       int tmp;
       for(auto w : G[x]) if(w.v != Fa)
       {
       	dfs1(w.v , x);
       	tmp = f[w.v] + w.c;
       	if(tmp > f[x]) g[x] = f[x] , f[x] = tmp;
       	else if(tmp > g[x]) g[x] = tmp;
       }
    }
    
    inline bool cmp(const int &A , const int &B) { return f[A] == f[B] ? A < B : f[A] < f[B]; }
    
    void dfs2(int x , int Fa)
    {
       int tmp;
       for(auto w : G[x]) if(w.v != Fa)
       {
       	tmp = w.c + ((f[w.v] + w.c == f[x]) ? g[x] : f[x]);
       	if(tmp > f[w.v]) g[w.v] = f[w.v] , f[w.v] = tmp;
       	else if(tmp > g[w.v]) g[w.v] = tmp;
       	dfs2(w.v , x);
       }
       for(auto w : G[x]) if(cmp(x , w.v)) up[w.v] = x; else up[x] = w.v;
    }
    
    int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
    
    void solve(int d)
    {
       for(int i = 1 ; i <= n ; ++i) fa[i] = i , siz[i] = 1;
       int ans = 0;
       for(int i = n , j = n ; i >= 1 ; --i)
       {
       	while(f[p[j]] > f[p[i]] + d) --siz[find(p[j--])];
       	ans = max(ans , siz[p[i]]); siz[fa[p[i]] = up[p[i]]] += siz[p[i]];
       }
       cout << ans << '
    ';
    }
    
    signed main()
    {
       n = read(); int u , v , c;
       for(int i = 1 ; i < n ; ++i)
       	u = read() , v = read() , c = read() , G[u].push_back(node(v , c)) , G[v].push_back(node(u , c));
       dfs1(1 , 0); dfs2(1 , 0);
       for(int i = 1 ; i <= n ; ++i) p[i] = i;
       sort(p + 1 , p + 1 + n , cmp);
       int Q = read(); while(Q--)  solve(read());
       return 0;
    }
    
  • 相关阅读:
    Javascript数组与字符串常用api
    javaScript入门(函数)
    javascript入门(1)
    微信小程序组件解读和分析:一、view(视图容器 )
    微信小程序组件解读和分析:十五、switch 开关选择器
    微信小程序组件解读和分析:十四、slider滑动选择器
    微信小程序组件解读和分析:十三、radio单选项目
    微信小程序组件解读和分析:十二、picker滚动选择器
    微信小程序组件解读和分析:十一、label标签
    微信小程序组件解读和分析:十、input输入框
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/13139752.html
Copyright © 2011-2022 走看看