This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// time_limit/yiping-qnlog2n-hld.cpp
// Complexity: O(qnlog^2 n)
// One can change the 'map' in 'DS' into other DS to obtain a complexity of O(qnlog n)
#include<bits/stdc++.h>
#include"tree.h"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 3e5 + 5;
const int inf = 0x3f3f3f3f;
struct Segment_Tree
{
	int mn[MAXN<<2], tag[MAXN<<2], n;
	#define ls(u) ((u)<<1)
	#define rs(u) ((u)<<1|1)
	#define lson(u) ls(u),l,mid
	#define rson(u) rs(u),mid+1,r
	inline void push_up(int u)
	{
		mn[u] = min(mn[ls(u)], mn[rs(u)]) + tag[u];
	}
	void build(int u,int l,int r)
	{
		mn[u] = 0; tag[u] = 0;
		if(l == r) return;
		int mid = (l+r)>>1;
		build(lson(u)); build(rson(u));
	}
	void add(int u,int l,int r,int ql,int qr,int k)
	{
		if(ql<=l && r<=qr){ tag[u] += k; mn[u] += k; return;}
		int mid = (l+r)>>1;
		if(ql<=mid) add(lson(u),ql,qr,k);
		if(mid<qr) add(rson(u),ql,qr,k);
		push_up(u);
	}
	int query(int u,int l,int r,int ql,int qr)
	{
		if(ql<=l && r<=qr) return mn[u];
		int mid = (l+r)>>1;
		if(ql<=mid && mid<qr) return min(query(lson(u),ql,qr), query(rson(u),ql,qr)) + tag[u];
		else return (ql<=mid? query(lson(u),ql,qr): query(rson(u),ql,qr)) + tag[u];
	}
	void init(int _n){ n = _n; build(1,1,n);}
	void add(int ql,int qr,int k){ if(ql<=qr) add(1,1,n,ql,qr,k);}
	int query(int ql,int qr){ return ql<=qr? query(1,1,n,ql,qr): inf;}
}tree;
int n;
vector<int> g[MAXN];
int anc[MAXN], wei[MAXN];
int siz[MAXN], dep[MAXN], son[MAXN];
void dfs_tree(int u,int fa)
{
	siz[u] = 1; son[u] = 0;
	for(int v: g[u]) if(v != fa)
	{
		dep[v] = dep[u] + 1;
		dfs_tree(v,u);
		siz[u] += siz[v];
		if(siz[v] > siz[son[u]]) son[u] = v;
	}
}
int dfn[MAXN], seq[MAXN], top[MAXN], curdfn;
void dfs_dfn(int u,int fa,int tp)
{
	top[u] = tp;
	dfn[u] = ++curdfn; seq[curdfn] = u;
	if(son[u]) dfs_dfn(son[u], u, tp);
	for(int v: g[u]) if(v != fa && v != son[u])
		dfs_dfn(v, u, v);
}
int getmin_path(int u,int v)// v is anc of u
{
	int res = inf;
	while(dep[top[u]] > dep[v])
		res = min(res, tree.query(dfn[top[u]], dfn[u])), u = anc[top[u]];
	res = min(res, tree.query(dfn[v] + 1, dfn[u]));
	return res;
}
void add_path(int u,int v,int k)// v is anc of u
{
	while(dep[top[u]] > dep[v])
		tree.add(dfn[top[u]], dfn[u], k), u = anc[top[u]];
	tree.add(dfn[v] + 1, dfn[u], k);
}
ll sum[MAXN];
set<pii> h[MAXN];
ll query(int ql,int qr)
{
	ll ans = 0;
	tree.init(n);
	for(int u=n; u>=1; --u)
	{
		h[u].clear();
		if(g[u].size() == 0)
		{
			ans += (ll)ql * wei[u];
			sum[u] = ql;
			h[u].emplace(wei[u], u);
			continue;
		}
		
		sum[u] = 0;
		h[u].emplace(wei[u], u);
		for(int v: g[u])
		{
			sum[u] += sum[v];
			if(h[u].size() < h[v].size())
				h[u].swap(h[v]);
			for(auto t: h[v])
				h[u].insert(t);
			h[v].clear();
		}
		
		while(sum[u] > qr)
		{
			auto v = h[u].begin() -> second;
			if(v == u)
			{
				ans += (sum[u] - qr) * wei[u];
				sum[u] = qr;
				break;
			}
			
			ll t = getmin_path(v, u);
			ll k = min(t, sum[u] - qr);
			
			if(k == 0)
			{
				h[u].erase(h[u].begin());
				continue;
			}
			
			ans += k * wei[v];
			add_path(v, u, -k);
			sum[u] -= k;
			
			if(t == k)
			{
				h[u].erase(h[u].begin());
			}
		}
		
		tree.add(dfn[u], dfn[u], sum[u] - ql);
	}
	
	return ans;
}
void init(vector<int> _anc, vector<int> _wei)
{
	n = (int)_anc.size();
	for(int i=1; i<=n; ++i)
		g[i].clear();
	for(int i=1; i<=n; ++i)
	{
		anc[i] = _anc[i-1] + 1;
		wei[i] = _wei[i-1];
		if(i > 1)
			g[anc[i]].emplace_back(i);
	}
	
	curdfn = 0; dep[1] = 0;
	dfs_tree(1,0);
	dfs_dfn(1,0,1);
}
| # | 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... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |