CF1019G Raining Season【边分治,凸包】
边分治 + Minkowski 和模板!
注意特判 \(n=1\) 的情况。
#include<bits/stdc++.h>
#define PB emplace_back
using namespace std;
typedef long long LL;
typedef tuple<int, int, int> tiii;
const int N = 200003;
template<typename T>
void read(T &x){
int ch = getchar(); x = 0; bool f = false;
for(;ch < '0' || ch > '9';ch = getchar()) f |= ch == '-';
for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
if(f) x = -x;
}
template<typename T>
bool chmin(T &a, const T &b){if(a > b) return a = b, 1; return 0;}
int n, m, head[N], to[N<<1], nxt[N<<1], va[N<<1], vb[N<<1];
vector<tiii> E[N];
void add(int u, int v, int a, int b){
static int cnt = 1;
to[++cnt] = v; nxt[cnt] = head[u]; head[u] = cnt; va[cnt] = a; vb[cnt] = b;
to[++cnt] = u; nxt[cnt] = head[v]; head[v] = cnt; va[cnt] = a; vb[cnt] = b;
}
void dfs(int x, int fa){
for(int i = 0;i < E[x].size();++ i)
if(get<0>(E[x][i]) == fa){
E[x].erase(E[x].begin() + i);
break;
}
for(auto _ : E[x]) dfs(get<0>(_), x);
while(E[x].size() > 2){
tiii s1 = E[x].back(); E[x].pop_back();
tiii s2 = E[x].back(); E[x].pop_back();
add(++n, get<0>(s1), get<1>(s1), get<2>(s1));
add(n, get<0>(s2), get<1>(s2), get<2>(s2));
E[x].PB(n, 0, 0);
}
for(auto _ : E[x]) add(x, get<0>(_), get<1>(_), get<2>(_));
}
struct Node {
LL x, y;
Node(LL _x = 0, LL _y = 0): x(_x), y(_y){}
bool operator < (const Node &o) const {return x < o.x || x == o.x && y < o.y;}
Node operator + (const Node &o) const {return Node(x + o.x, y + o.y);}
Node operator - (const Node &o) const {return Node(x - o.x, y - o.y);}
LL operator * (const Node &o) const {return x * o.y - y * o.x;}
LL val(LL a){return x * a + y;}
};
int siz[N], S, rt, MX;
bool vis[N<<1];
void getrt(int x, int fa){
siz[x] = 1;
for(int i = head[x];i;i = nxt[i])
if(to[i] != fa && !vis[i]){
getrt(to[i], x);
siz[x] += siz[to[i]];
if(chmin(MX, abs((siz[to[i]]<<1)-S)))
rt = i;
}
}
void get_hull(vector<Node> &v){
if(v.size() < 2) return;
vector<Node> hul;
sort(v.begin(), v.end());
hul.PB(v[0]); hul.PB(v[1]);
for(int i = 2;i < v.size();++ i){
while(hul.size() > 1 && (hul.back() - hul[hul.size()-2]) * (v[i] - hul.back()) >= 0)
hul.pop_back();
hul.PB(v[i]);
}
v = hul;
}
vector<Node> all, pa, pb;
void calc(vector<Node> &pp, int x, int fa, LL sa, LL sb){
pp.PB(sa, sb);
for(int i = head[x];i;i = nxt[i])
if(to[i] != fa && !vis[i])
calc(pp, to[i], x, sa + va[i], sb + vb[i]);
}
void solve(int x){
MX = 1e9; getrt(x, 0);
int a = to[rt], b = to[rt^1];
vis[rt] = vis[rt^1] = true;
pa.resize(0); pb.resize(0);
calc(pa, a, b, va[rt], vb[rt]);
calc(pb, b, a, 0, 0);
get_hull(pa); get_hull(pb);
int ia = 0, ib = 0;
while(ia+1 < pa.size() || ib+1 < pb.size()){
all.PB(pa[ia] + pb[ib]);
if(ia+1 == pa.size() || ib+1 < pb.size() && (pa[ia+1] - pa[ia]) * (pb[ib+1] - pb[ib]) > 0) ++ ib;
else ++ ia;
}
all.PB(pa.back() + pb.back());
if(siz[a] > siz[b]) siz[a] = S - siz[b];
else siz[b] = S - siz[a];
if((S = siz[a]) > 1) solve(a);
if((S = siz[b]) > 1) solve(b);
}
int main(){
read(n); read(m);
if(n == 1){for(int i = 0;i < m;++ i) printf("0 "); return 0;}
for(int i = 1, u, v, a, b;i < n;++ i){
read(u); read(v); read(a); read(b);
E[u].PB(v, a, b); E[v].PB(u, a, b);
} dfs(1, 0); S = n; solve(1); get_hull(all);
for(int i = 0, j = 0;i < m;++ i){
while(j+1 < all.size() && all[j+1].val(i) > all[j].val(i)) ++ j;
printf("%lld ", all[j].val(i));
}
}