QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#187775#1085. Brave Seekers of UnicornsSublimeTextTL 0ms0kbC++146.3kb2023-09-24 22:11:042023-09-24 22:11:05

Judging History

你现在查看的是最新测评结果

  • [2023-09-24 22:11:05]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:0kb
  • [2023-09-24 22:11:04]
  • 提交

answer

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <set>
#include <cmath>
#include <map>
#include <unordered_map>
#include <iomanip>
#include <stack>
#include <queue>
#include <vector>
#include <unordered_set>
#include <assert.h>
#include <bitset>
#include <tuple>
using namespace std;
typedef long long ll;
#define int long long
namespace Main {

	void read(int &x) {
		x = 0;
		char ch = getchar();
		while (!(47 < ch && ch < 58)) ch = getchar();
		while (47 < ch && ch < 58) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
	}
	const int N=1e5+5;
	int n,k;
	struct edge {
		int nxt, to, val;
	} e[N << 1];
	int h[N], num;
	inline void addedge(int x, int y, int z) {
		e[++num].nxt = h[x];
		e[num].to = y;
		e[num].val = z;
		h[x] = num;
	}

	namespace sub { //k=1时的简单换根
		#define fir first
		#define sec second
		pair<ll, int> f[N], g[N];
		void add(int u, int v, int i) {
			if(f[u].fir < f[v].fir + e[i].val) {
				g[u] = f[u];
				f[u].fir = f[v].fir + e[i].val;
				f[u].sec = v;
			}
			else if(g[u].fir < f[v].fir + e[i].val) {
				g[u].fir = f[v].fir + e[i].val;
				g[u].sec = v;
			}
		}
		void del(int u, int v) {
			if(f[u].second == v) f[u] = g[u];
		}
		void dfs(int u, int prt) {
			f[u] = {0, 0}, g[u] = {0, 0};
			for (int i = h[u]; i; i = e[i].nxt) {
				int v = e[i].to;
				if(v == prt) continue;
				dfs(v, u);
				add(u, v, i);
			}
		}
		ll ans[N];
		void dp(int u, int prt) {
			ans[u] = f[u].first;
			for (int i = h[u]; i; i = e[i].nxt) {
				int v = e[i].to;
				if(v == prt) continue;
				del(u, v);
				add(v, u, i);
				dp(v, u);
				del(v, u);
				add(u, v, i);
			}
		}
		void solve() {
			dfs(1, 0);
			dp(1, 0);
			for (int r = 1; r <= n; ++r) {
				printf("%lld\n", ans[r]);
			} 
		}
		#undef fir
		#undef sec
	}
	ll len[N];
	int son[N];
	int fa[N], val[N];
	void dfs1(int u,int prt) {
		len[u] = 0;
		son[u] = 0;
		fa[u] = prt;
		for (int i = h[u]; i; i = e[i].nxt){
			int v = e[i].to;
			if(v == prt) continue;
			dfs1(v, u);
			val[v] = e[i].val;
			if(len[u] <= len[v] + val[v]) len[u] = len[v] + val[v], son[u] = v;
		}
		// cout << u << ' ' << len[u] << ' ' << son[u] << '\n';
	}
	int top[N], scc[N];
	ll w[N];
	//top:链头,scc:将每条链的信息记录在叶子上
	//w: 链的权值
	void dfs2(int u, int f) {
		top[u] = f;
		scc[u] = u;
		if(son[u]) {
			dfs2(son[u], f);
			scc[u] = scc[son[u]];
		}
		for (int i = h[u]; i; i = e[i].nxt) {
			int v = e[i].to;
			if(v == fa[u] || v == son[u]) continue;
			dfs2(v, v);
		}
		// cout << u << ' ' << scc[u] << '\n';
	}
	ll ans[N];
	multiset<ll> a, b;
	ll sum;
	//a:前k大, b:除了前k大的链
	//sum:前k大的和
	void add(ll v) {
		a.insert(v);
		sum += v;
		if((int)(a.size()) > k) {
			b.insert(*a.begin());
			sum -= *a.begin();
			a.erase(a.begin());
		}
	}
	void del(ll v) {
		if(a.find(v) != a.end()) { //是否在前k大当中
			a.erase(a.find(v));
			sum -= v;
			if(b.size()) {
				//将b中最大加入前k大
				sum += *--b.end();
				a.insert(*--b.end());
				b.erase(--b.end());
			}
		}
		else {
			b.erase(b.find(v));
		}
	}
	void add(int u, ll v) { //x所在链添加v
		if(!u) return;
		// cout << w[u] << '\n';
		del(w[u]);
		w[u] += v;
		// if(u == 4 && v > 0) cerr << "add = " << w[u] << '\n';
		// if(u == 4 && v < 0) cerr << "sub = " << w[u] << '\n';
		add(w[u]);
	}
	void dp(int u, int prt) {
		ans[u] = sum;
		//求一个次长的儿子
		int son2 = 0;
		ll maxlen = 0;

		for (int i = h[u]; i; i = e[i].nxt){
			int v = e[i].to;
			if(v == son[u]) continue;
			if(maxlen <= len[v] + e[i].val)
				maxlen = len[v] + e[i].val, son2 = v;
		}

		// cout << u << ' ' << son[u] << ' ' << son2 << ' ' << maxlen << '\n';

		for (int i = h[u]; i; i = e[i].nxt) {
			int v = e[i].to;
			if(v == prt) continue;
			ll tmp_len = len[u];
			if (v != son[u]) {	
				//修改长儿子
				add(scc[u], e[i].val), add(scc[v], -e[i].val);
				// if(u == 1) cout << scc[u] << ' ' << scc[v] << '\n';
				int tmp_son = son[v], tmp_scc = scc[v];

				son[v] = u, scc[v] = scc[son[v]];
				
				len[u] = len[son[u]] + val[son[u]];
				// cout <<"@@@@@@@@@@@@@@\n";
				// cout << v << '\n';
				dp(v, u);
				// cout << "#############\n";
				//回撤
				son[v] = tmp_son, scc[v] = tmp_scc;
				len[u] = tmp_len;
				// if(scc[u] == 4) cout << "scc[4] = " << u << '\n';
				add(scc[v], e[i].val), add(scc[u], -e[i].val);
				// if(u == 1) cout << e[i].val << ' ' << w[scc[u]] << '\n';
			}
			else {
				//修改次长儿子
				// if(u == 1) cout << w[scc[u]] << '\n';
				add(scc[u], -e[i].val), add(scc[son2], e[i].val);
				len[u] = len[son2] + val[son2];
				int tmp_son2 = son[u], tmp_son1 = -1, tmp_sccu = scc[u], tmp_sccv = scc[v];
				// if(u == 1) cout << w[scc[son2]] <<' ' << w[scc[u]] << '\n';
				if (w[scc[son2]] > w[scc[u]]) {
					// if(u == 1)cout << u << ' ' << v << '\n';
					tmp_son1 = son[v];
					son[u] = son2, scc[u] = scc[son[u]];
					// if(u == 1 && v == 2) cerr << "OK" << ' ' << son[v] << '\n';
					son[v] = u, scc[v] = scc[son[v]];
				}
				else son[u] = son2, scc[u] = scc[son[u]];

				dp(v, u);

				//回撤
				if(son2 != -1) {
					son[v] = tmp_son1, scc[v] = tmp_sccv;
					son[u] = tmp_son2, scc[u] = tmp_sccu;
				}
				else {
					son[u] = tmp_son2, scc[u] = tmp_sccu;
				}
				len[u] = tmp_len;
				add(scc[son2], -e[i].val), add(scc[u], e[i].val);
			}
		}
	}
	int main() {
//		ios :: sync_with_stdio(false);
//		cin.tie(0), cout.tie(0);
		read(n), read(k);
		for (int i = 1, x, y, z; i < n; ++i) {
			read(x), read(y), read(z);
			addedge(x, y, z);
			addedge(y, x, z);
		}
		bool test = 1;
		if(k == 1 && test) {
			sub::solve();
			return 0;
		}
		dfs1(1, 0);
		dfs2(1, 1);
		for (int i = 1; i <= n; ++i) {
			if (scc[i] == i) { //链尾叶子
				w[i] = len[top[i]] + val[top[i]];
				// if(top[i] == 1) cout << w[i] << '\n';
				add(w[i]);
				// cout << w[i] << '\n';
			}
		}
		// cout << scc[1] << ' ' << w[scc[1]] << '\n';
		dp(1, 0);
		for (int i = 1; i <= n; ++i) {
			printf("%lld\n", ans[i]);
		}
//		while(1);
		return 0;
	}
}
signed main() {
	    
//	freopen("ex_2.in", "r", stdin);
	
	
	Main :: main();
	return 0;
} 
//meb:8460kb=8mb

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Time Limit Exceeded

input:

1

output:


result: