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 <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define INF 100000000000000000
#define int long long
#define lchild(i) (i*2 + 1)
#define rchild(i) (i*2 + 2)
#define mid(l, u) ((l+u)/2)
#define x(p) p.first
#define y(p) p.second
#define MOD 998244353
#define ordered_set tree<pair<int, int>, null_type,less<pair<int, int>>, rb_tree_tag,tree_order_statistics_node_update>
using namespace std;
struct plan{
int A, B, C, lca;
};
const int N = 1e5 + 5;
int n, m;
vector<int> adj[N];
int seg[10*N];
int dep[N];
int ind[N];
int endd[N];
int dp[N][2]; //0 -> without including i, 1 -> including i
plan plans[N];
vector<int> ett;
vector<pair<int, int>> children[N];
vector<plan> PlansHere[N];
int dpseg[10*N][2];
int merge(int l, int u){
return (dep[l]<=dep[u]) ? l : u;
}
int build(int l, int u, int i){
if(l==u) return seg[i] = ett[l];
else return seg[i] = merge(build(l, mid(l, u), lchild(i)), build(mid(l, u)+1, u, rchild(i)));
}
int query(int l, int u, int i, int ll, int uu){
//cout<<l<<" "<<u<<" "<<ll<<" "<<uu<<endl;
if(l>=ll && u<=uu) return seg[i];
if(uu<=mid(l, u)) return query(l, mid(l, u), lchild(i), ll, uu);
if(ll>mid(l, u)) return query(mid(l, u)+1, u, rchild(i), ll, uu);
return merge(query(l, mid(l, u), lchild(i), ll, uu), query(mid(l, u)+1, u, rchild(i), ll, uu));
}
int query1(int l, int u, int i, int ll, int uu, int id){
if(l>=ll && u<=uu) return dpseg[i][id];
if(l>uu || u<ll) return 0;
return query1(l, mid(l, u), lchild(i), ll, uu, id) + query1(mid(l, u)+1, u, rchild(i), ll, uu, id);
}
int upd1(int l, int u, int i, int ll, int upval, int id){
if(l>=ll && u<=ll) return dpseg[i][id] = dpseg[i][id] + upval;
if(l>ll || u<ll) return dpseg[i][id];
return dpseg[i][id] = upd1(l, mid(l, u), lchild(i), ll, upval, id) + upd1(mid(l, u)+1, u, rchild(i), ll, upval, id);
}
int LCA(int x, int y){
return query(0, ett.size() - 1, 0, min(ind[x], ind[y]), max(ind[x], ind[y]));
}
void buildLCA(){
build(0, ett.size()-1, 0);
}
void euler_tour(int i, int p, int d){
//cout<<i<<" "<<p<<endl;
dep[i] = d;
ind[i] = ett.size();
ett.push_back(i);
for(int j: adj[i]){
if(j==p) continue;
children[i].push_back({ett.size(), j});
euler_tour(j, i, d+1);
ett.push_back(i);
}
endd[i] = ett.size();
}
int findChild(int i, int j){
//find the child of i that contains j
int ans = -1;
int lo = 0;
int hi = children[i].size() - 1;
while(lo<=hi){
int mid = mid(lo, hi);
//cout<<lo<<" "<<hi<<"\n";
//cout<<i<<" "<<j<<" "<<children[i][mid].first<<" "<<ind[j]<<"\n";
if(children[i][mid].first <= ind[j]){
//cout<<children[i][mid].second<<"\n";
ans = max(ans, mid);
lo = mid + 1;
}
else hi = mid - 1;
}
//cout<<i<<" is connected to "<<j<<" through "<<(children[i][ans].second)<<endl;
return children[i][ans].second;
}
int qpath(int x, int y, int id){
int l = LCA(x, y);
int tr = 0;
if(x!=l) tr += query1(0, ett.size()-1, 0, min(ind[x], ind[l]), max(ind[x], ind[l]),id);
if(y!=l) tr += query1(0, ett.size()-1, 0, min(ind[y], ind[l]), max(ind[y], ind[l]), id);
return tr;
}
int update(int x, int dp0, int dp1){
upd1(0, ett.size()-1, 0, ind[x], dp0, 0);
upd1(0, ett.size()-1, 0, ind[x], dp1, 1);
if(endd[x] < ett.size()){
upd1(0, ett.size()-1, 0, endd[x], -dp0, 0);
upd1(0, ett.size()-1, 0, endd[x], -dp1, 1);
}
}
int dfs(int i){
dp[i][0] = 0;
for(pair<int, int> j: children[i]){
dp[i][0] += dfs(j.second);
}
int maxi = dp[i][0];
for(plan k: PlansHere[i]){
int contr = 0;
int plancontr = k.C;
contr = qpath(k.A, k.B, 0);
contr -= qpath(k.A, k.B, 1);
maxi = max(maxi, dp[i][0] + contr + plancontr);
}
dp[i][1] = maxi;
update(i, dp[i][0], dp[i][1]);
//cout<<i<<" "<<dp[i][0]<<" "<<dp[i][1]<<endl;
return dp[i][1];
}
signed main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin>>n;
for(int i = 1;i<n;i++){
int x, y;
cin>>x>>y;
adj[x].push_back(y);
adj[y].push_back(x);
}
euler_tour(1, 0, 0);
buildLCA();
cin>>m;
for(int i = 0;i<m;i++){
cin>>plans[i].A>>plans[i].B>>plans[i].C;
//cout<<"Done taking input"<<endl;
plans[i].lca = LCA(plans[i].A, plans[i].B);
//cout<<"Done calculating LCA"<<endl;
PlansHere[plans[i].lca].push_back(plans[i]);
//cout<<"Done pushing back"<<endl;
}
/*for(int i = 1;i<=n;i++){
for(plan j: PlansHere[i]){
cout<<i<<" -> ("<<j.A<<", "<<j.B<<", "<<j.C<<")"<<endl;
}
}*/
cout<<dfs(1)<<"\n";
}
/*
7
3 4
6 5
2 7
1 5
7 5
4 5
5
4 3 10
5 6 5
2 6 9
7 2 2
1 3 8
8
1 2
2 3
3 4
4 5
5 6
6 7
7 8
5
7 5 4
5 8 9
4 3 9
1 3 3
2 8 11
20
17 10
11 4
8 3
3 16
1 14
15 18
5 4
6 18
10 18
19 4
16 7
2 13
4 12
12 20
9 20
18 13
20 14
14 7
13 7
15
19 9 2341
13 8 6974
8 3 3339
15 17 6515
10 13 4370
1 7 8376
18 2 9272
6 7 4595
1 20 505
10 9 308
6 19 8937
2 15 5072
5 4 4217
2 4 4170
19 12 8204
10
10 6
2 7
1 9
9 8
3 8
6 4
7 8
5 4
4 8
7
1 3 1
4 10 1
2 8 1
5 3 1
3 7 1
8 5 1
1 9 1
*/
Compilation message (stderr)
election_campaign.cpp: In function 'long long int update(long long int, long long int, long long int)':
election_campaign.cpp:102:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if(endd[x] < ett.size()){
~~~~~~~~^~~~~~~~~~~~
election_campaign.cpp:106:1: warning: no return statement in function returning non-void [-Wreturn-type]
}
^
# | 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... |