• 【HDU】HDU5664 Lady CA and the graph


    原题链接

    题解

    距离省选只有一周了我居然才开始数据结构康复计划

    这题很简单,就是点分树,然后二分一个值,我们计算有多少条路径大于这个值
    对于一个点分树上的重心,我们可以通过双指针的方法求出它子树里的路径任意搭配大于这个值的方案
    然后同一个子树里重复计算的删掉
    再计算和自己祖先之间的路径

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 50005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    struct node {
        int to,next,val;
    }E[MAXN * 2];
    
    int N,sumE,head[MAXN],rt;
    int64 K;
    
    int dep[MAXN],fa[MAXN][20],d[MAXN],zz[MAXN];
    
    bool vis[MAXN];
    
    vector<int> poi;
    vector<int> dis[2][MAXN];
    int tot;
    void add(int u,int v,int c) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        E[sumE].val = c;
        head[u] = sumE;
    }
    void dfs(int u) {
        zz[u] = zz[fa[u][0]] + 1;
        for(int i = 1 ; i <= 18 ; ++i) fa[u][i] = fa[fa[u][i - 1]][i - 1];
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa[u][0]) {
    	    fa[v][0] = u;
    	    dep[v] = dep[u] + E[i].val;
    	    dfs(v);
    	}
        }
    }
    int que[MAXN],ql,qr;
    int Calc_G(int st) {
        static int f[MAXN],siz[MAXN],son[MAXN];
        ql = 1;qr = 0;
        que[++qr] = st;f[st] = 0;siz[st] = 1;son[st] = 0;
        while(ql <= qr) {
    	int u = que[ql++];
    	for(int i = head[u] ; i ; i = E[i].next) {
    	    int v = E[i].to;
    	    if(v != f[u] && !vis[v]) {
    		siz[v] = 1;son[v] = 0;
    		f[v] = u;que[++qr] = v;
    	    }
    	}
        }
        int res = que[qr];
        for(int i = qr ; i >= 1 ; --i) {
    	int u = que[i];
    	if(f[u]) {
    	    siz[f[u]] += siz[u];
    	    son[f[u]] = max(son[f[u]],siz[u]);
    	}
    	son[u] = max(son[u],qr - siz[u]);
    	if(son[u] < son[res]) res = u;
        }
        return res;
    }
    void dfs_for_dis(int u,int f) {
        poi.pb(u);
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != f && !vis[v]) {
    	    d[v] = d[u] + E[i].val;
    	    dfs_for_dis(v,u);
    	}
        }
    }
    
    void dfs_divide(int u) {
        int G = Calc_G(u);
        vis[G] = 1;
        for(int i = head[G] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!vis[v]) {
    	    poi.clear();
    	    d[v] = E[i].val;
    	    dfs_for_dis(v,G);
    	    ++tot;
    	    for(int j = 0 ; j < poi.size() ; ++j) {
    		dis[1][tot].pb(d[poi[j]]);
    		dis[0][G].pb(d[poi[j]]);
    	    }
    	}
        }
        for(int i = head[G] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!vis[v]) dfs_divide(v);
        }
    }
    int64 check(int mid) {
        int64 res = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	int l = 0,r = dis[0][i].size() - 1;
    	while(r >= 0) {
    	    while(l < dis[0][i].size() && dis[0][i][r] + dis[0][i][l] < mid) ++l;
    	    if(dis[0][i][r] >= mid) res += 2;
    	    res += dis[0][i].size() - l;
    	    --r;
    	}
    	l = 0,r = dis[1][i].size() - 1;
    	while(r >= 0) {
    	    while(l < dis[1][i].size() && dis[1][i][r] + dis[1][i][l] < mid) ++l;
    	    res -= dis[1][i].size() - l;
    	    --r;
    	}
        }
        res /= 2;
        for(int i = 1 ; i <= N ; ++i) {
    	int t = dep[i] - mid;
    	int u = i;
    	for(int j = 18 ; j >= 0 ; --j) {
    	    if(fa[u][j] && dep[fa[u][j]] > t) {
    		u = fa[u][j];
    	    }
    	}
    	res -= zz[u] - zz[rt];
        }
        return res;
    }
    void Init() {
        read(N);read(rt);read(K);
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        sumE = 0;tot = 0;
        for(int i = 1 ; i <= N ; ++i) {dis[0][i].clear();dis[1][i].clear();}
        
        int u,v,c;
        for(int i = 1 ; i < N ; ++i) {
    	read(u);read(v);read(c);
    	add(u,v,c);add(v,u,c);
        }
        dep[rt] = 0;
        fa[rt][0] = 0;
        dfs(rt);
        dfs_divide(rt);
        for(int i = 1 ; i <= N ; ++i) {
    	sort(dis[0][i].begin(),dis[0][i].end());
    	sort(dis[1][i].begin(),dis[1][i].end());
        }
    }
    void Solve() {
        Init();
        int L = 0,R = 500000001;
        while(L < R) {
    	int mid = (L + R + 1) >> 1;
    	if(check(mid) >= K) L = mid;
    	else R = mid - 1;
        }
        if(R == 0) {puts("NO");return;}
        out(L);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        int T;
        read(T);
        while(T--) Solve();
    }
    
  • 相关阅读:
    SQL语句之奇形怪状的冷门函数
    计算累计收益
    关于SQL表字段值缺失的处理办法
    虚拟机移植到另一台机器
    分分钟搞懂rank() over(partition by)的使用
    分分钟搞懂union与union all
    【转】10分钟就能学会的.NET Core配置
    【转】依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题
    【转】Asp.Net Core2.0获取客户IP地址,及解决发布到Ubuntu服务器获取不到正确IP解决办法
    【转】在.net Core 中像以前那样的使用HttpContext.Current
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10638749.html
Copyright © 2020-2023  润新知