• 【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();
    }
    
  • 相关阅读:
    RTC驱动程序分析
    Linux下的RTC子系统
    [置顶] 谈EXPORT_SYMBOL使用
    《Linux内核修炼之道》精华分享与讨论(5)——Kernel地图:Kconfig与Makefile
    写出高效优美的单片机C语言代码
    哈夫曼树
    如何提高浮点数变整数的精度
    CF798C Mike and gcd problem
    CF822C Hacker, pack your bags!
    CF821C Okabe and Boxes
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10638749.html
Copyright © 2020-2023  润新知