Gym101174F.Performance Review(可持久化线段树)

版权声明:Amove? https://blog.csdn.net/Amovement/article/details/88350342

                                                                                        Performance Review
Employee performance reviews are a necessary evil in any
company. In a performance review, employees give written
feedback about each other on the work done recently. This
feedback is passed up to their managers which then decide
promotions based on the feedback received.
Maria is in charge of the performance review system in the
engineering division of a famous company. The division follows
a typical structure. Each employee (except the engineering
director) reports to one manager and every employee reports
directly or indirectly to the director.
Having the managers assessing the performance of their direct
reports has not worked very well. After thorough research,
Maria came up with a new performance review system. The
main idea is to complement the existing corporate structure with a technical rank for each
employee. An employee should give feedback only about subordinates with lower technical
level.
Hence, the performance review will work as follows. Employees prepare a summary of their
work, estimate how much time it takes to review it, and then request their superiors with
higher technical rank to review their work.
Maria is very proud of this new system, but she is unsure if it will be feasible in practice. She
wonders how much time each employee will waste writing reviews. Can you help her out?
Task
Given the corporate structure of the engineering division, determine how much time each
employee will spend writing performance reviews.
Input
The rst line of input has one integer E, the number of employees, who are conveniently
numbered between 1 and E. The next E lines describe all the employees, starting at employee
1 until employee E. Each line contains three space-separated integers mi ri ti
, the manager,
the technical rank and the expected time to perform the review of employee i. The engineering
director has no manager, represented with mi = −1. The other employees have mi between 1
and E.

Constraints
1 ≤ E ≤ 100 000 Number of employees
1 ≤ ri ≤ 100 000 Technical rank of each employee
1 ≤ ti ≤ 100 000 Expected time to perform each review
Output
The output contains E lines. Line i has the time employee i will spend writing reviews.

Sample Input
5
4 4 80
1 1 40
-1 10 60
3 5 50
4 8 70

Sample Output
40
0
240
120
0

一、原题地址

点我传送

二、大致题意

有n个人,每个人有自己的上级 father,并且每个人有自己的物理等级level ,每个人向上级做汇报需要wi的时间。

现在询问,对于一个人 i 来说,他听取下级的所有汇报需要多少时间,只有那些物理等级level比自己低并且在图上是自己下级的人才需要听取报告。

输出每个人听取报告花费的时间。

三、大致思路

题目的意思相当与让我们求解子树上等级低于自己的边权和。为了方便先把边权投影在点上,然后维护点权。先跑一编DFS序,根据DFS建可持久化线段树,线段树以level为区间更新权值。

四、冗长的代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<functional>
using namespace std;
const int inf = 0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;
#define LL long long int
long long  gcd(long long  a, long long  b) { return a == 0 ? b : gcd(b % a, a); }

#define LL long long int


const int maxn=100005;
int cnt;
int rt[maxn];

struct Node
{
	int ls, rs, l, r;
	LL sum;
}tr[maxn*33];


void PushUp(int i)
{
	tr[i].sum = tr[tr[i].ls].sum + tr[tr[i].rs].sum;
}

int Build(int l,int r)
{
	int pos = ++cnt;
	if (l == r)
	{
		tr[pos].sum = 0;
		return pos;
	}
	int mid = (l + r) >> 1;
	tr[pos].ls = Build(l,mid);
	tr[pos].rs = Build(++mid,r);
	return pos;
}
//第零号版本的线段树

LL Query(int ed,int l,int r,int ql,int qr)
{                           //ed是 版本号
	if (ql<=l && r<=qr) return tr[ed].sum;
	int mid = (l + r) >> 1;
	if (qr <= mid) return Query(tr[ed].ls,l,mid,ql,qr);
	else if(ql>mid)return Query(tr[ed].rs,mid+1,r,ql,qr);
	else
    {
        return Query(tr[ed].ls,l,mid,ql,mid)+Query(tr[ed].rs,mid+1,r,mid+1,qr);
    }
}
//查询第ed个版本的线段树[ql,qr]上的和

int update(int ed,int l,int r,int p,LL k)
{
	int pos = ++cnt;
    tr[pos].sum=tr[ed].sum;
	if (l == r)
	{
		tr[pos].sum += k;
		return pos;
	}
	tr[pos].ls = tr[ed].ls;
	tr[pos].rs = tr[ed].rs;

	int mid = (l + r) >> 1;
	if (p <= mid) tr[pos].ls = update(tr[ed].ls,l,mid,p,k);
	else tr[pos].rs = update(tr[ed].rs,++mid,r,p,k);
	PushUp(pos);
	return pos;
}
//单点更新p点的值加上k
//返回值为新的版本树的根节点

struct Edge
{
	int u, v;
	LL w;
	Edge() {}
	Edge(int _u, int _v, LL _w)
	{
		u = _u; v = _v;
		w = _w;
	}
};
vector<Edge>e[maxn];
int nodeId,root;
int Head[maxn], Tail[maxn];
int level[maxn],father[maxn];
LL ans[maxn];

void DFS(int nx, int pre,LL w)
{
	Head[nx] = ++nodeId;
	rt[nodeId]=update(rt[nodeId - 1], 0, 100000 , level[nx], w);
	for (int i = 0; i < e[nx].size(); i++)
	{
		int  to = e[nx][i].v;
		DFS(to, nx, e[nx][i].w);
	}
	Tail[nx] = nodeId;
	ans[nx] = Query(rt[Tail[nx]],0,100000,0,level[nx]-1)-Query(rt[Head[nx]-1],0,100000,0,level[nx]-1);
}


int main()
{
	int n;
	scanf("%d",&n);
	rt[0]=Build(0,100000);//建树的范围可随题意变化
	for (int i = 1; i <= n; i++)
	{
		LL w;
		scanf("%d %d %lld", &father[i], &level[i], &w);
		if (father[i] == -1)father[i] = 0, root = i;
		e[father[i]].push_back(Edge(father[i], i, w));
	}
	DFS(root, 0, 0);
	for (int i = 1; i <= n; i++)
	{
		printf("%lld\n", ans[i]);
	}
}

猜你喜欢

转载自blog.csdn.net/Amovement/article/details/88350342