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. python BeautifulSoup4

    source form  http://www.bkjia.com/ASPjc/908009.html 昨天把传说中的BeautifulSoup4装上了,还没有装好的童鞋,请看本人的上一篇博客: Py ...

  2. python实现Linux启动守护进程

    python实现Linux启动守护进程 DaemonClass.py代码: #/usr/bin/env python # -*- coding: utf-8 -*- import sys import ...

  3. Yocto开发笔记之《串口驱动调试》(QQ交流群:519230208)

    QQ群:519230208,为避免广告骚扰,申请时请注明 “开发者” 字样 ======================================================== 串口驱动各 ...

  4. php 数据访问(以mysql数据库为例)

    //建一个连接,造一个连接对象$db = new MySQLi("localhost","root","123","mydb&qu ...

  5. JQuery------Select标签的各种使用方法

    optioin属性(value) <option value='>Hello</option> option的点击事件 <select class="s-one ...

  6. 使用RawSocket进行网络抓包

    aw socket,即原始套接字,可以接收本机网卡上的数据帧或者数据包,对与监听网络的流量和分析是很有作用的,一共可以有3种方式创建这种socket. 中文名 原始套接字 外文名 RAW SOCKET ...

  7. 国内GIT托管服务

    http://www.cnblogs.com/TianFang/p/3348949.html

  8. JS中的 公有变量、私有变量 !

    公有变量.私有变量 ! 初学者的见解,算是记录学习过程,也算是分享以便共同成长,如有不正确的地方,还请不吝赐教! 先看代码1: function car(){ var wheel = 3; //私有变 ...

  9. layoutSubviews方法需要被调用的情况有哪些

    layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写 layoutSubviews在以下情况下会被调用: 1.init初始化不会触发layoutSubviews 但是是用i ...

  10. Ubuntu14.04 LTS更新源

    Ubuntu14.04 LTS更新源 不同的网络状况连接以下源的速度不同, 建议在添加前手动验证以下源的连接速度(ping下就行),选择最快的源可以节省大批下载时间. 首先备份源列表: sudo cp ...