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. 深入JVM-垃圾回收概念与算法

    一.认识垃圾回收 谈到垃圾回收(Garbage Collection,简称GC),GC中的垃圾,特指存在于内存中的.不会再被使用的对象.对于内存空间的管理来说,识别和清理垃圾对象是至关重要的. 二.常 ...

  2. Linux Canbus调试笔记

    STM32之CAN---错误管理分析      牛人博客 http://blog.csdn.net/flydream0/article/details/8161418 CAN总线在嵌入式Linux下驱 ...

  3. Objective -C学习笔记 之copy(复制)

    //自定义类对象实现copy需要遵守copy协议(否则程序崩溃),实现必须实现的协议方法,里面的代码就决定了你的copy是深是浅 #import <Foundation/Foundation.h ...

  4. css3实现小黄人

    效果就像这样: 不废话,直接上代码! hrml代码: <!DOCTYPE html> <html> <head lang="zh"> <m ...

  5. 蛋疼的vs

    这个vs2008 难用的很,要是叫我选肯定vs高版本的,vs2012或者直接vs2015

  6. mysql主从复制 转

    mysql服务器的主从配置,这样可以实现读写分离,也可以在主库挂掉后从备用库中恢复.需要两台机器,安装mysql,两台机器要在相通的局域网内,可以分布在不同的服务器上,也可以在一台服务器上启动多个服务 ...

  7. 对Java垃圾回收最大的误解是什么

    当 我还是小孩的时候,父母常说如果你不好好学习,就只能去扫大街了.但他们不知道的是,清理垃圾实际上是很棒的一件事.可能这也是即使在Java的世界中, 同样有很多开发者对GC算法产生误解的原因--包括它 ...

  8. JavaWeb学习笔记——JSP标准标签库JSTL

  9. /MD, /MT, /LD (Use Run-Time Library)

    https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx

  10. Nancy总结(二)记一次Nancy 框架中遇到的坑

    记一次Nancy 框架中遇到的坑 前几天,公司一个项目运行很久的Nancy框架的网站,遇到了一个很诡异的问题.Session 对象跳转到另外一个页面的时候,session对象被清空了,导致用户登录不上 ...