蓝题训练9.27F. Unique Occurrences

F. Unique Occurrences
Tag:
题意:略

题解:线段树分治我做做做

参考代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll W = 5e5 + 7, N=5e5 + 7,M = 5e5 + 7;
ll n, m, k, u[M], v[M], fa[N], sz[N],ans;
struct T {
	ll l, r;
	vector<ll> e;
} t[W<<2];
stack<pair<ll,ll>> s;
ll ls(ll x){
	return x<<1;
}
ll rs(ll x){
	return (x<<1)|1;
}
void build(ll p, ll l, ll r) {
	t[p].l = l, t[p].r = r;
	if (l == r) return;
	ll mid=(l+r)/2;
	build(ls(p), l, mid), 
	build(rs(p), mid + 1, r);
}
void ins(ll p, ll l, ll r, ll x) {
	if (t[p].l >= l && t[p].r <= r) {
		t[p].e.push_back(x);
		return;
	}
	ll mid = (t[p].l + t[p].r) / 2;
	if (l <= mid) ins(ls(p), l, r, x);
	if (r > mid) ins(rs(p), l, r, x);
}
inline ll find(ll x) {
	while (x != fa[x]) x = fa[x];
    return x;
}
inline void merge(ll x, ll y) {
	if (x == y) return;
	if (sz[x] > sz[y]) swap(x, y);
	s.push({x,sz[x]}), fa[x] = y, sz[y]+=sz[x];
}
vector<pair<ll,ll>> a[500005];
void dfs(ll p, ll l, ll r) {
	ll o = s.size();
	for (ll i = 0; i < t[p].e.size(); i++) {
		ll x = t[p].e[i], z = find(u[x]), y = find(v[x]);
		if (z == y) {
			continue;
		}
		merge(z,y);
	}
	if(l==r){
		for(auto j:a[l]){
			ll uu=j.first;ll vv=j.second;
			while(uu!=fa[uu]) uu=fa[uu];
			while(vv!=fa[vv]) vv=fa[vv];
			ans+=sz[uu]*sz[vv];
		}
	}
	else{
		ll mid=(l+r)/2;
		dfs(ls(p), l, mid); dfs(rs(p), mid + 1, r);
	}
	while (s.size() > o) {
		sz[fa[s.top().first]] -= s.top().second;
		fa[s.top().first] = s.top().first;
		s.pop();
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n;
	build(1,1,n);
	for (ll i = 1, w; i <= n-1; i++) {
		cin>>u[i]>>v[i]>>w;
		if (w==1) ins(1,2,n,i);
		else if(w==n) ins(1,1,n-1,i);
		else{
			ins(1,1,w-1,i);
			ins(1,w+1,n,i);
		}
		a[w].push_back({u[i],v[i]});
	}
	for (int i = 1; i <= n; i++) fa[i] = i,sz[i]=1;
	ans=0;
	dfs(1, 1, n);
	cout<<ans<<"\n";
	return 0;
}//注意每个部分开的范围不同的题可能不一样



posted @ 2026-10-30 09:26  pigeon666  阅读(3)  评论(0)    收藏  举报