zoukankan      html  css  js  c++  java
  • [BZOJ4317]Atm的树

    [BZOJ4317]Atm的树

    试题描述

    Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree……
    于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的点有一个距离(什么是距离不用说吧),他需要对于每个点回答:从这个点出发的第k小距离是多少;
    如果atm不能回答出来,那么明天4019的闹钟将不会响,4019全寝可能就迟到了,所以atm希望你帮帮他。

    输入

    第一行,两个正整数n,k,表示树的点数,询问的是第几小距离;
    第二~n行,每行三个正整数x,y,w,表示x和y之间有一条边,x为父亲,边权为w;

    输出

    n行, 每行一个数,第i行输出从i开始第k小距离

    输入示例

    5 2
    1 5 2
    1 2 4
    2 3 6
    2 4 5

    输出示例

    4
    5
    10
    9
    6

    数据规模及约定

    100% n<=15000, 边权在1~10之间,为了方便,保证1为根;K<=5000

    题解

    参见这道题

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 15010
    #define maxm 30010
    #define maxlog 15
    
    int n, m, head[maxn], nxt[maxm], to[maxm], dist[maxm];
    
    void AddEdge(int a, int b, int c) {
    	to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
    	swap(a, b);
    	to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
    	return ;
    }
    
    int mnd[maxlog][maxn<<1], Log[maxn<<1], clo, dep[maxn], dfn[maxn];
    void build(int u, int pa) {
    	mnd[0][dfn[u] = ++clo] = dep[u];
    	for(int e = head[u]; e; e = nxt[e]) if(to[e] != pa)
    		dep[to[e]] = dep[u] + dist[e], build(to[e], u), mnd[0][++clo] = dep[u];
    	return ;
    }
    void rmq_init() {
    	Log[1] = 0;
    	for(int i = 2; i <= clo; i++) Log[i] = Log[i>>1] + 1;
    	for(int j = 1; (1 << j) <= clo; j++)
    		for(int i = 1; i + (1 << j) - 1 <= clo; i++)
    			mnd[j][i] = min(mnd[j-1][i], mnd[j-1][i+(1<<j-1)]);
    	return ;
    }
    int cdist(int a, int b) {
    	int l = dfn[a], r = dfn[b];
    	if(l > r) swap(l, r);
    	int t = Log[r-l+1];
    	return dep[a] + dep[b] - (min(mnd[t][l], mnd[t][r-(1<<t)+1]) << 1);
    }
    
    #define maxnode 1800010
    
    struct Node {
    	int v, r, siz;
    	Node() {}
    	Node(int _, int __): v(_), r(__) {}
    };
    struct Treap {
    	Node ns[maxnode];
    	int ToT, fa[maxnode], ch[maxnode][2];
    	
    	void maintain(int o) {
    		if(!o) return ;
    		ns[o].siz = 1;
    		for(int i = 0; i < 2; i++) if(ch[o][i])
    			ns[o].siz += ns[ch[o][i]].siz;
    		return ;
    	}
    	void rotate(int u) {
    		int y = fa[u], z = fa[y], l = 0, r = 1; 
    		if(z) ch[z][ch[z][1]==y] = u;
    		if(ch[y][1] == u) swap(l, r);
    		fa[u] = z; fa[y] = u; fa[ch[u][r]] = y;
    		ch[y][l] = ch[u][r]; ch[u][r] = y;
    		maintain(y); maintain(u);
    		return ;
    	}
    	void Insert(int& o, int v) {
    		if(!o) {
    			ns[o = ++ToT] = Node(v, rand());
    			return maintain(o);
    		}
    		bool d = v > ns[o].v;
    		Insert(ch[o][d], v); fa[ch[o][d]] = o;
    		if(ns[ch[o][d]].r > ns[o].r) {
    			int t = ch[o][d];
    			rotate(t); o = t;
    		}
    		return maintain(o);
    	}
    	int query(int o, int v) {
    		if(!o) return 0;
    		int ls = ch[o][0] ? ns[ch[o][0]].siz : 0;
    		if(v < ns[o].v) return query(ch[o][0], v);
    		return ls + 1 + query(ch[o][1], v);
    	}
    } sol;
    
    int f[maxn], siz[maxn], rt, size;
    bool vis[maxn];
    void getroot(int u, int pa) {
    	siz[u] = 1; f[u] = 0;
    	for(int e = head[u]; e; e = nxt[e]) if(to[e] != pa && !vis[to[e]]) {
    		getroot(to[e], u);
    		siz[u] += siz[to[e]];
    		f[u] = max(f[u], siz[to[e]]);
    	}
    	f[u] = max(f[u], size - siz[u]);
    	if(f[rt] > f[u]) rt = u;
    	return ;
    }
    void dfs(int u, int pa) {
    	siz[u] = 1;
    	for(int e = head[u]; e; e = nxt[e]) if(to[e] != pa && !vis[to[e]])
    		dfs(to[e], u), siz[u] += siz[to[e]];
    	return ;
    }
    int fa[maxn];
    void solve(int u) {
    	vis[u] = 1;
    	for(int e = head[u]; e; e = nxt[e]) if(!vis[to[e]]) {
    		dfs(to[e], u);
    		f[rt = 0] = size = siz[to[e]]; getroot(to[e], u);
    		fa[rt] = u; solve(rt);
    	}
    	return ;
    }
    
    int Rt[maxn], Rtfa[maxn];
    void update(int s) {
    	sol.Insert(Rt[s], 0);
    	for(int u = s; fa[u]; u = fa[u]) {
    		int d = cdist(s, fa[u]);
    //		printf("insert:: %d(fa: %d): %d
    ", u, fa[u], d);
    		sol.Insert(Rtfa[u], d);
    		sol.Insert(Rt[fa[u]], d);
    	}
    	return ;
    }
    int query(int s, int x) {
    	int ans = sol.query(Rt[s], x);
    //	printf("base: %d
    ", ans);
    	for(int u = s; fa[u]; u = fa[u]) {
    		int d = cdist(s, fa[u]);
    //		printf("query:: %d(fa: %d): %d (%d - %d)
    ", u, fa[u], x - d, sol.query(Rt[fa[u]], x - d), sol.query(Rtfa[u], x - d));
    		ans += sol.query(Rt[fa[u]], x - d) - sol.query(Rtfa[u], x - d);
    	}
    	return ans;
    }
    
    int main() {
    	n = read(); int K = read(), sum = 0;
    	for(int i = 1; i < n; i++) {
    		int a = read(), b = read(), c = read();
    		AddEdge(a, b, c); sum += c;
    	}
    	
    	build(1, 0);
    	rmq_init();
    	f[rt = 0] = size = n; getroot(1, 0);
    	solve(rt);
    //	for(int i = 1; i <= n; i++) printf("(%d)%d%c", i, fa[i], i < n ? ' ' : '
    ');
    	for(int i = 1; i <= n; i++) update(i);
    	for(int i = 1; i <= n; i++) {
    		int l = 1, r = sum;
    		while(l < r) {
    			int mid = l + r >> 1;
    			if(query(i, mid) - 1 < K) l = mid + 1; else r = mid;
    		}
    		printf("%d
    ", l);
    	}
    	
    	return 0;
    }
    

    又 1A 啦 2333333!

    双倍经验:BZOJ2051,改改数据范围。

  • 相关阅读:
    [转]HD钱包的助记词与密钥生成原理
    [转]简单科普私钥、地址、助记词、Keystore的区别
    [转]Sequelize 中文API文档-4. 查询与原始查询
    [转]Node.JS使用Sequelize操作MySQL
    [转]OmniLayer / omnicore API 中文版
    [转]usdt omnicore testnet 测试网络
    [转]USDT与omniCore钱包
    [转]BTC RPC API GetTransaction
    [转]比特币测试链——Testnet介绍
    [转]BTC手续费计算,如何设置手续费
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6666690.html
Copyright © 2011-2022 走看看