计量大学 A A Party for You Started

A A Party for You Started

Welcome to the grand party for CJLUACMerCJLUACMerCJLUACMer, we are glad about your arrival. Before starting, please remind that the difficulty of all the problems is absolutely not relevant to its order of permutation, so please consider the order of accomplishment by yourself. Now let us get started!

CJLUACMerCJLUACMerCJLUACMer comes from NNN factions. Some factions with the majority of people, based on broad range fields, such as Mathematics, and others may be more specific, such as Geometry, Algebra. Moreover, it contains complex relationships beyond different types of factions. For example, let faction 111(Geometry) belongs to faction 222(Mathematics) if there are two people from faction 111 and one person from faction 222 initially. We can say there are two people belongs to faction 111 or three people belongs to faction 222. People attending parties like to ask if somebody is present, so when someone from a certain faction comes, he(or she) will ask the security guard GYQGYQGYQ how many people have come from another particular faction, maybe wide range or just minority.

Generally, every moment there will be xxx people who belong to the faction uuu arrive at the party, and they will ask how many people had come from the faction vvv. The security guard GYQGYQGYQ had to run in to check the number of people every time, so he was so busy and sweaty.

Now given that CJLUACMerCJLUACMerCJLUACMer has NNN factions in total and MMM groups of people who come to the party once at a time. And given an array aaa, the index aia_iai represents the parent faction of the iii-th faction, it's guaranteed that each specific faction belongs to only one superior faction(which means just a level higher), and there is exactly one 000 in the array, which indicates the whole CJLUACMCJLUACMCJLUACM association and this faction is the largest. After that, there will be MMM queries within the format of u x v, whose meaning is as described above. Could you help the security guard GYQGYQGYQ answer every query?

Input Specification:

Each input file only contains one test case.

The first line contains two integers NNN and MMM (111NNN222 × 10410^4104, 111MMM10510^5105), indicating the number of the factions and the queries.

The second line contains NNN integers a1a_1a1, a2a_2a2,……, ana_nan (111aia_iaiNNN), indicating the parent faction of the iii-th faction, and there is exactly one 000 in the array.

Then followed MMM lines, each line contains three integers uuu, xxx, vvv (111uuu, vvvNNN, 111xxx10910^9109), indicating there are xxx people who belong to the faction uuu arrive at the party, and they asked how many people had come from the faction vvv.

Output Specification:

Print MMM lines, each line contains an integer indicating the answer of the security guard GYQGYQGYQ in order.

Sample Input:

4 5
0 1 1 2
1 2 2
2 1 2
4 1 2
3 1 3
3 1 4

  
  

Sample Output:

0
2
3
2
4

  
  

题意

聚会开始啦。
有很多人要进场,然后每个人会一个技能,技能们之间是一棵树。
举一个简单的例子,会数学的同学就会几何和代数,所以有一个人会数学就会有一个人会代数,但是会代数的人不一定会几何hhh
给定一颗技能树,每次先询问会场中会某项技能的人的数量,然后给某个节点加上 X X X个人(需要对子技能的所有节点也加上人数)。

简析

树链部分,队友写的hhhh

参考代码

#include <bits/stdc++.h>
using namespace std;
const int N = 20005;
typedef long long ll;
struct Edge {
	int to, next;
}edge[N * 2];

int head[N], tot;
int top[N], fa[N], deep[N], num[N], p[N], fp[N], son[N], pos;

void init() {
	tot = 0;
	memset(head, -1, sizeof head);
	pos = 1;
	memset(son, -1, sizeof son);
}

void addedge(int u, int v) {
	edge[tot].to = v, edge[tot].next = head[u], head[u] = tot++;
}

void dfs1(int u, int pre, int d) {
	deep[u] = d;
	fa[u] = pre;
	num[u] = 1;
	for (int i = head[u]; ~i; i = edge[i].next) {
		int v = edge[i].to;
		if (v != pre) {
			dfs1(v, u, d + 1);
			num[u] += num[v];
			if (son[u] == -1 || num[v] > num[son[u]]) {
				son[u] = v;
			}
		}
	}
}

void getpos(int u, int sp) {
	top[u] = sp;
	p[u] = pos++;
	fp[p[u]] = u;
	if (son[u] == -1) return;
	getpos(son[u], sp);
	for (int i = head[u]; ~i; i = edge[i].next) {
		int v = edge[i].to;
		if (v != son[u] && v != fa[u])
			getpos(v, v);
	}
}

int lowbit(int x) {
	return x & (-x);
}

ll c[N];
int n;
ll sum(int i) {
	ll s = 0;
	while (i > 0) {
		s += c[i];
		i -= lowbit(i);
	}
	return s;
}

void add(int i, int val) {
	while (i <= n) {
		c[i] += val;
		i += lowbit(i);
	}
}

void Change(int u, int v, int val) {
	int f1 = top[u], f2 = top[v];
	int tmp = 0;
	while (f1 != f2) {
		if (deep[f1] < deep[f2]) {
			swap(f1, f2);
			swap(u, v);
		}
		add(p[f1], val);
		add(p[u] + 1, -val);
		u = fa[f1];
		f1 = top[u];
	}
	if (deep[u] > deep[v]) swap(u, v);
	add(p[u], val);
	add(p[v] + 1, -val);
}
int a[N];

void modify(int u, int val)
{
	int f1 = p[u], f2 = p[u] + num[u] - 1;
	add(f2 + 1, -val), add(f1, val);
}

int main() {
	// freopen("in.txt", "r", stdin);
	int m;
	scanf("%d%d", &n, &m);
	init();
	int pa, root;
	for (int i = 1; i <= n; ++i)
	{
		scanf("%d", &pa);
		if (pa == 0)
		{
			root = i;
		}
		else
		{
			addedge(pa, i);
			addedge(i, pa);
		}
	}

	dfs1(root, 0, 0);
	getpos(root, root);
	
	memset(c, 0, sizeof c);

	int u, x, v;
	while (m--)
	{
		scanf("%d%d%d", &u, &x, &v);

		printf("%lld\n", sum(p[v]));

		modify(u, x);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值