列表

详情


NC232181. 露西、天空与钻石

描述

天空中有许多钻石。

露西发现天空中的钻石总是呈一个树形结构。

开始天空中有一个根节点(编号为 ),根节点上有  个钻石,每个钻石的美丽程度都是 

天空中发生了  个事件,第  个事件有两种:

1.给定整数 ,表示天空中出现了一个新节点(编号为 ),这个节点的父亲是 。在这个节点上有  个钻石,每个钻石的美丽程度都是 
2.给定整数 ,表示露西准备从节点  到根节点的路径上的所有节点中摘走正好  颗钻石,且美丽程度之和最大。当两个节点上的钻石的美丽程度相同时,露西会优先取编号大的节点上的钻石。如果路径上没有足够的钻石,露西会摘走全部的钻石。(事件之间不独立)

对于每种二号事件,你要求出摘到的钻石数量和最大美丽之和。


输入描述


本题强制在线。

第一行三个整数 ),分别表示事件个数,根节点上钻石个数和美丽程度。

接下来  行,第  行的输入为以下两种格式中的一种:

),表示发生了事件一。其中  为  加密后的结果,真实的  为上一次询问中两个问题的答案之和,如果没有上一次询问则 

),表示发生了事件二。

操作含义详见题目描述,保证操作中节点  存在。


输出描述

对于每个二号事件,一行两个整数分别表示摘到的钻石数和美丽程度之和。

示例1

输入:

10 10 1
2 0 7
1 0 4 4
1 0 2 8
1 1 4 7
1 0 2 7
2 5 15
1 3 3 4
1 1 5 5
1 5 3 3
2 9 9

输出:

7 7
15 77
6 21

说明:

强制在线前的输入:
10 10 1
2 0 7
1 0 4 4
1 2 2 8
1 3 4 7
1 4 2 7
2 5 15
1 4 3 4
1 5 5 5
1 7 3 3
2 9 9

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 596ms, 内存消耗: 6432K, 提交时间: 2022-03-10 21:23:54

#include <bits/stdc++.h>
const int MaxN = 2e5 + 5;

int q, a[MaxN], c[MaxN];
int fa[MaxN], ch[MaxN][2], mx[MaxN];

void pushup(int x)
{
	mx[x] = x;
	for(int p : {ch[x][0], ch[x][1]})
	if(std::tie(a[mx[p]], mx[p]) > std::tie(a[mx[x]], mx[x])) mx[x] = mx[p];
}

bool isroot(int x) {return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}

int get(int x) {return (ch[fa[x]][0] == x ? 0 : 1);}

void rotate(int x)
{
	int k = get(x), y = fa[x], z = fa[y];
	if(!isroot(y)) ch[z][get(y)] = x;
	ch[y][k] = ch[x][k ^ 1]; fa[ch[y][k]] = y;
	ch[x][k ^ 1] = y; fa[y] = x; fa[x] = z;
	pushup(y); pushup(x);
}

void splay(int x)
{
	for(int f = fa[x]; !isroot(x); rotate(x), f = fa[x])
	if(!isroot(f)) rotate(get(x) == get(f) ? f : x);
}

void access(int x)
{
	for(int p = 0; x; p = x, x = fa[x]) splay(x), ch[x][1] = p, pushup(x);
}

int main()
{
	int64_t lastans = 0;
	std::cin >> q >> c[1] >> a[1];
	pushup(1);
	
	for(int i = 1, opt, f, v, w; i <= q; ++i)
	{
		std::cin >> opt;
		if(opt == 1)
		{
			std::cin >> f >> c[i + 1] >> a[i + 1];
			fa[i + 1] = (f + lastans) % i + 1;
			pushup(i + 1);
		}
		else
		{
			std::cin >> v >> w; ++v;
			access(v);
			
			int cnt = 0; int64_t sum = 0;
			
			while(true)
			{
				splay(v);
				int t = mx[v]; if(a[t] == 0) break;
				int x = std::min(c[t], w);
				cnt += x; sum += int64_t(x) * a[t];
				if((c[t] -= x) == 0) splay(t), a[t] = 0, pushup(t);
				if((w -= x) == 0) break;
			}
			
			std::cout << cnt << " " << sum << "\n";
			lastans = cnt + sum;
		}
	}
	return 0;
}

上一题