This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/*
https://oj.uz/problem/view/JOI15_election_campaign
100 points sol
*/
#include<iostream>
#include<vector>
#include<string.h>
#define ll long long
#define pi pair < ll,ll >
#define mp(a,b) make_pair(a,b)
#define MAX_N 200004
using namespace std;
vector < int > graph[MAX_N];
vector < pair < pi,ll > > tours[MAX_N];
ll jump_memo[MAX_N][21];
ll tin[MAX_N],tout[MAX_N],cur_time;
ll dp[MAX_N],S[MAX_N];
ll seg[4*MAX_N];
int n,m;
int jump(int x,int i) // find 2^i -th ancestor of x
{
if(jump_memo[x][i] != -1)
return jump_memo[x][i];
return jump_memo[x][i] = jump(jump(x,i-1),i-1);
}
bool is_ancestor(int x,int y) // returns if x is ancestor of y
{
return (tin[x] <= tin[y] && tout[x] >= tout[y]);
}
int get_lca(int x,int y)
{
if(is_ancestor(x,y))
return x;
if(is_ancestor(y,x))
return y;
for(int i = 20;i >= 0;i--)
{
if(!is_ancestor(jump(x,i),y))
x = jump(x,i);
}
return jump(x,0);
}
void dfs(int cur,int par)
{
tin[cur] = cur_time++;
jump_memo[cur][0] = par;
for(int i = 0;i < graph[cur].size();i++)
{
int v = graph[cur][i];
if(v == par)
continue;
dfs(v,cur);
}
tout[cur] = cur_time++;
return;
}
void initialize()
{
memset(jump_memo,-1,sizeof jump_memo);
memset(dp,-1,sizeof dp);
dfs(1,1);
return;
}
void input()
{
int a,b,c;
cin >> n;
for(int i = 0;i < n-1;i++)
{
cin >> a >> b;
graph[a].push_back(b);
graph[b].push_back(a);
}
initialize();
cin >> m;
for(int i = 0;i < m;i++)
{
cin >> a >> b >> c;
tours[get_lca(a,b)].push_back(mp(mp(a,b),c));
}
return;
}
void update(int low,int high,int pos,int slow,int val)
{
if(low == high && low == slow)
{
seg[pos] = val;
return;
}
if(low>slow||high<slow)
return;
int mid = (low+high)/2;
update(low,mid,pos*2+1,slow,val);
update(mid+1,high,pos*2+2,slow,val);
seg[pos] = seg[pos*2+1]+seg[pos*2+2];
return;
}
ll query(int low,int high,int pos,int slow,int shigh)
{
if(low >= slow && high <= shigh)
return seg[pos];
if(low>shigh || high < slow)
return 0;
int mid = (low+high)/2;
return query(low,mid,pos*2+1,slow,shigh) + query(mid+1,high,pos*2+2,slow,shigh);
}
ll go(int cur,int target) // get value to add on path cur->target
{
return query(0,2*n,0,tin[cur],tin[target])+S[target];
}
ll calc(int cur,int par)
{
if(dp[cur] != -1)
return dp[cur];
for(int i = 0;i < graph[cur].size();i++)
{
int v = graph[cur][i];
if(v==par)
continue;
S[cur] += calc(v,cur); // S = sum of dp of children
}
dp[cur] = S[cur]; // for now. dp[cur] = S[cur] if we don't do a tour on cur
for(int i = 0;i < graph[cur].size();i++)
{
int v = graph[cur][i];
if(v==par)
continue;
update(0,2*n,0,tin[v],S[cur]-dp[v]); // we hold this value to utilize it in the go function. look at O(NM) implementation
update(0,2*n,0,tout[v],-S[cur]+dp[v]); // we add opposite value, to get path sum
}
for(int i = 0;i < tours[cur].size();i++)
{
int x = tours[cur][i].first.first; // first endpoint
int y = tours[cur][i].first.second; // second endpoint
int C = tours[cur][i].second; // gain of tour
dp[cur] = max(dp[cur],go(cur,x)+go(cur,y) - S[cur] + C); // S[cur] is counted twice
}
return dp[cur];
}
void solve()
{
cout << calc(1,1) << endl;
return;
}
int main()
{
input(); // read input and initialize tree
solve(); // solve problem
return 0;
}
Compilation message (stderr)
election_campaign.cpp: In function 'void dfs(int, int)':
election_campaign.cpp:59:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
59 | for(int i = 0;i < graph[cur].size();i++)
| ~~^~~~~~~~~~~~~~~~~~~
election_campaign.cpp: In function 'long long int calc(int, int)':
election_campaign.cpp:146:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
146 | for(int i = 0;i < graph[cur].size();i++)
| ~~^~~~~~~~~~~~~~~~~~~
election_campaign.cpp:157:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
157 | for(int i = 0;i < graph[cur].size();i++)
| ~~^~~~~~~~~~~~~~~~~~~
election_campaign.cpp:167:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<std::pair<long long int, long long int>, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
167 | for(int i = 0;i < tours[cur].size();i++)
| ~~^~~~~~~~~~~~~~~~~~~
# | 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... |