蓝题训练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;
}//注意每个部分开的范围不同的题可能不一样

浙公网安备 33010602011771号