0、题意:给出一个N个结点的树,每条边有一个正整数权值,定义两个结点的距离为连接这两个结点路径上边权的和。对于每个结点i,它到其他N-1个结点都有一个距离,将这些距离从小到大排序,输出第K个距离。

1、分析:这个题我问了一下Claris,然后理解了,我们存下logn个分支结构,然后我们在分治结构中二分就好了QAQ

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 2000010

inline int read(){
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

struct Edge{
    int u, v, w, next;
} G[M];
int head[M], ed;
int size, f[M], son[M], ok[M];
int cnt, now;
int V[2][M], g[M], nxt[M], W[M], ED;
int rl[M], rr[M], el[M], er[M];
int q[M], tot, n, m;

inline void add(int u, int v, int w){
    G[++ ed] = (Edge){u, v, w, head[u]};
    head[u] = ed;
}

inline void ADD(int u, int v1, int v2, int w){
    V[0][++ ED] = v1;
    V[1][ED] = v2;
    nxt[ED] = g[u];
    g[u] = ED;
    W[ED] = w;
}

inline void FindRoot(int x, int fa){
    son[x] = 1; f[x] = 0;
    for(int i = head[x]; i != -1; i = G[i].next) if(G[i].v != fa && !ok[i]){
        FindRoot(G[i].v, x);
        son[x] += son[G[i].v];
        if(son[G[i].v] > f[x]) f[x] = son[G[i].v];
    }
    if(size - son[x] > f[x]) f[x] = size - son[x];
    if(f[x] < f[now]) now = x;
}

inline void dfs(int x, int fa, int dis){
    q[++ tot] = dis;
    for(int i = head[x]; i != -1; i = G[i].next) if(G[i].v != fa && !ok[i]){
        dfs(G[i].v, x, dis + G[i].w);
    }
}

inline void dfs2(int x, int fa, int dis){
    ADD(x, now, cnt, dis);
    q[++ tot] = dis;
    for(int i = head[x]; i != -1; i = G[i].next) if(G[i].v != fa && !ok[i]){
        dfs2(G[i].v, x, dis + G[i].w);
    }
}

inline void solve(int x){
    q[rl[x] = ++ tot] = 0;
    for(int i = head[x]; i != -1; i = G[i].next) if(!ok[i]){
        dfs(G[i].v, x, G[i].w);
    }
    sort(q + rl[x], q + tot + 1);
    rr[x] = tot;
    for(int i = head[x]; i != -1; i = G[i].next) if(!ok[i]){
        el[++ cnt] = tot + 1;
        dfs2(G[i].v, x, G[i].w);
        sort(q + el[cnt], q + tot + 1);
        er[cnt] = tot;
    }
    for(int i = head[x]; i != -1; i = G[i].next) if(!ok[i]){
        ok[i ^ 1] = 1;
        f[0] = size = son[G[i].v];
        FindRoot(G[i].v, now = 0);
        solve(now);
    }
}

inline int ask(int L, int r, int x){
    int l = L, t = l - 1, mid;
    while(l <= r){
        mid = (l + r) / 2;
        if(q[mid] <= x) l = (t = mid) + 1;
        else r = mid - 1;
    }
    return t - L + 1;
}

inline int query(int x, int k){
    int t = ask(rl[x], rr[x], k) - 1;
    for(int i = g[x]; i != -1; i = nxt[i]) t += ask(rl[V[0][i]], rr[V[0][i]], k - W[i]) - ask(el[V[1][i]], er[V[1][i]], k - W[i]);
    return t;
}
inline int getans(int x){
    int l = 1, r = 10000 * (n - 1), mid;
    while(l < r){
      mid = (l + r) / 2;
      if(query(x, mid) < m) l = mid + 1;
      else r = mid;
    }
    return l;
}

int main(){
    n = read(), m = read();
    memset(head, -1, sizeof(head)); ED = ed = -1;
    memset(g, -1, sizeof(g));
    for(int i = 1; i < n; i ++){
        int u = read(), v = read(), w = read();
        add(u, v, w); add(v, u, w);
    }
    size = f[0] = n;
    FindRoot(1, now = 0);
    solve(now);
    for(int i = 1; i <= n; i ++) printf("%d\n", getans(i));
    return 0;
}

BZOJ2051——A Problem For Fun的更多相关文章

  1. [BZOJ2051]A Problem For Fun/[BZOJ2117]Crash的旅游计划/[BZOJ4317]Atm的树

    [BZOJ2051]A Problem For Fun/[BZOJ2117]Crash的旅游计划/[BZOJ4317]Atm的树 题目大意: 给出一个\(n(n\le10^5)\)个结点的树,每条边有 ...

  2. BZOJ2051 : A Problem For Fun

    树的点分治,将点分治的过程记录下来,每一个分治结构按到分治中心的距离维护所有点. 对于一个点二分答案,然后在$O(\log n)$个分治结构中二分查找,时间复杂度$O(n\log^3n)$. #inc ...

  3. 1199 Problem B: 大小关系

    求有限集传递闭包的 Floyd Warshall 算法(矩阵实现) 其实就三重循环.zzuoj 1199 题 链接 http://acm.zzu.edu.cn:8000/problem.php?id= ...

  4. No-args constructor for class X does not exist. Register an InstanceCreator with Gson for this type to fix this problem.

    Gson解析JSON字符串时出现了下面的错误: No-args constructor for class X does not exist. Register an InstanceCreator ...

  5. C - NP-Hard Problem(二分图判定-染色法)

    C - NP-Hard Problem Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:262144 ...

  6. Time Consume Problem

    I joined the NodeJS online Course three weeks ago, but now I'm late about 2 weeks. I pay the codesch ...

  7. Programming Contest Problem Types

        Programming Contest Problem Types Hal Burch conducted an analysis over spring break of 1999 and ...

  8. hdu1032 Train Problem II (卡特兰数)

    题意: 给你一个数n,表示有n辆火车,编号从1到n,入站,问你有多少种出站的可能.    (题于文末) 知识点: ps:百度百科的卡特兰数讲的不错,注意看其参考的博客. 卡特兰数(Catalan):前 ...

  9. BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 4032  Solved: 1817[Submit] ...

随机推荐

  1. 从Paxos到ZooKeeper-一、分布式架构

    本系列为本人读<从Paxos到ZooKeeper>一书的一些读书笔记,仅供学习使用,谢谢. 一.从集中式到分布式 1.1 分布式的定义: 分布式系统是一个硬件或软件组件分布在不同的网络计算 ...

  2. sql自带函数语句

    --取数值表达式的绝对值select abs(-41)      41select abs(41)       41select abs(-41.12)   41.12select abs(41.12 ...

  3. AppleHDA 10.9.3 disassm 1

    1.通过AppleHDAFunctionGroupFactory::createAppleHDAFunctionGroup(DevIdStruct *)实际创建相应的 AppleHDAFunction ...

  4. WinForm------TextEdit控件内容字体变*号

    "属性" -> “Properties” -> “LookAndFeel” -> “PasswordChar”

  5. mysql查询区分大小写

    Mysql默认查询是不分大小写的,可以在SQL语句中加入 binary来区分大小写: BINARY不是函数,是类型转换运算符,它用来强制它后面的字符串为一个二进制字符串,可以理解为在字符串比较的时候区 ...

  6. Java排序算法——冒泡排序

    import java.util.Arrays; //================================================= // File Name : Bubble_S ...

  7. 固定导航(Sticky nav)

    方法1: <div class="footer"></div> .footer{ position:fixed; bottom:0; left:0; wid ...

  8. JAVA利用Zip4j解压缩【转】

    官方地址:http://www.lingala.net/zip4j/(需要FQ) jar包:http://pan.baidu.com/s/145hwI 演示包:http://pan.baidu.com ...

  9. 再说linux中的rm mv 遍历执行多个文件的操作: find + xagrs

    参考文章: http://cfqtyaogang.blog.163.com/blog/static/218051022011812111342203/, 这篇文章讲得很全面很详细... 包括不好理解的 ...

  10. 关于精简安装office2010的步骤

    首先我们安装系统都会安装一个办公套件:office当然你也可以选择使用wps但我个人比较讨厌wps的广告 然而使用office完整安装不仅消耗资源大启动速度慢,而且一些功能我都用不到,所以我这几来一个 ...