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));
	}
}
posted @ 2021-06-01 16:40  mizu164  阅读(54)  评论(0编辑  收藏  举报