This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "roads.h"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int n,d[100001],p[1000001],level[1000001];
ll dp[100001][2],w[100001],sum;
vector<int> deg;
vector<pii> adj[100001];
vector<ll> ans;
bool comp(pii a, pii b) {return a.second<b.second;}
bool comp2(int a, int b) {return level[a]>level[b];}
bool comp3(int a, int b) {return d[a]>d[b];}
struct node {
int cnt,prior;
ll val,sum;
node *l, *r;
node(ll v) : cnt(1), val(v), sum(v), prior(rand()), l(NULL), r(NULL) {}
};
typedef node* pnode;
pnode tr[100001];
void upd(pnode t) {
if (t) {
t->cnt=1;
t->sum=t->val;
if (t->l) {
t->cnt+=t->l->cnt;
t->sum+=t->l->sum;
}
if (t->r) {
t->cnt+=t->r->cnt;
t->sum+=t->r->sum;
}
}
}
int get_cnt(pnode t) {
if (!t) return 0;
else return t->cnt;
}
void split1(pnode t, pnode &l, pnode &r, int v) { //split by cnt
if (t==NULL) l=r=NULL;
else if (get_cnt(t->l)>=v) split1(t->l,l,t->l,v), r=t;
else split1(t->r,t->r,r,v-get_cnt(t->l)-1), l=t;
upd(t);
}
void split2(pnode t, pnode &l, pnode &r, int v) { //split by val
if (t==NULL) l=r=NULL;
else if (t->val>=v) split2(t->l,l,t->l,v), r=t;
else split2(t->r,t->r,r,v), l=t;
upd(t);
}
void merge(pnode l, pnode r, pnode &t) {
if (!l) t=r;
else if (!r) t=l;
else if (l->prior>=r->prior) merge(l->r,r,l->r), t=l;
else merge(l,r->l,r->l), t=r;
upd(t);
}
void dfs(int x, int par) {
p[x]=par;
level[x]=level[par]+1;
for (auto s : adj[x]) {
if (s.first==par) continue;
w[s.first]=s.second;
merge(tr[x],new node(s.second),tr[x]);
dfs(s.first,x);
}
}
void cal(int x, int want) {
pnode A,B,C;
ll pre=dp[x][1]-dp[x][0];
//find dp[x][0], don't cut the edge above it
split1(tr[x],A,B,adj[x].size()-want);
if (A) dp[x][0]=A->sum;
else dp[x][0]=0;
merge(A,B,tr[x]);
if (x) {
//find dp[x][1], cut the edge above it
split1(tr[x],A,B,adj[x].size()-want-1);
if (A) dp[x][1]=A->sum+w[x];
else dp[x][1]=w[x];
merge(A,B,tr[x]);
//replace the value of the parent by dp[x][1]-dp[x][0]
int par=p[x];
split2(tr[par],A,B,pre);
split1(B,C,B,1);
merge(A,B,tr[par]);
ll nw=dp[x][1]-dp[x][0];
if (d[x]==want+1) nw=w[x];
split2(tr[par],A,B,nw+1);
merge(A,new node(nw),A);
merge(A,B,tr[par]);
}
}
vector<ll> minimum_closure_costs(int N, vector<int> U, vector<int> V, vector<int> W) {
n=N;
for (int i=0; i<n-1; ++i) {
adj[U[i]].push_back(pii(V[i],W[i]));
adj[V[i]].push_back(pii(U[i],W[i]));
++d[U[i]]; ++d[V[i]];
}
for (int i=0; i<n; ++i) deg.push_back(i), sort(adj[i].begin(),adj[i].end(),comp);
sort(deg.begin(),deg.end(),comp3);
dfs(0,0);
p[0]=-1;
for (int i=1; i<n; ++i) dp[i][1]=w[i], sum+=w[i];
ans.push_back(sum);
for (int i=1; i<3; ++i) {
sum=0;
while (!deg.empty()) {
if (d[deg.back()]<i+1) deg.pop_back();
else break;
}
vector<int> v;
for (auto s : deg) v.push_back(s);
sort(v.begin(),v.end(),comp2);
for (auto s : v) {
cal(s,i);
if (d[p[s]]<=i && p[s]!=-1) sum+=min(dp[s][0],dp[s][1]);
else sum+=dp[s][0];
}
ans.push_back(sum);
}
return ans;
}
Compilation message (stderr)
roads.cpp: In constructor 'node::node(ll)':
roads.cpp:19:12: warning: 'node::sum' will be initialized after [-Wreorder]
19 | ll val,sum;
| ^~~
roads.cpp:18:13: warning: 'int node::prior' [-Wreorder]
18 | int cnt,prior;
| ^~~~~
roads.cpp:22:5: warning: when initialized here [-Wreorder]
22 | node(ll v) : cnt(1), val(v), sum(v), prior(rand()), l(NULL), r(NULL) {}
| ^~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |