QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#187775 | #1085. Brave Seekers of Unicorns | SublimeText | TL | 0ms | 0kb | C++14 | 6.3kb | 2023-09-24 22:11:04 | 2023-09-24 22:11:05 |
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