现在的位置: 首页 > 综合 > 正文

SWUN 1440 – 你的工资是多少

2012年09月27日 ⁄ 综合 ⁄ 共 2261字 ⁄ 字号 评论关闭

 

你的工资是多少

时间限制(普通/Java) : 2000 MS/ 6000 MS          运行内存限制 : 65536 KByte
总提交 : 9            测试通过 : 3

描述

 

   民大ACM团队毕业的成员,聚到一起开了一家IT公司。营业期间,公司的利润也是时而涨时儿跌,大家不得不感叹创业之艰辛。

   当然,作为ACMer出身,公司对工资的调整是非常严谨的,按团队或个人贡献,进行严格审批。

   公司的共有n个员工,每个员工的编号分别是Di(1<=i<=n),并且公司中有着严格的团队分类制度。每个下属有且只有一个直属上司,每个上司可能有多个下属。公司中只有一个总裁,并且总裁为D1,即i=1。除了总裁之外,所有员工都有自己的上司。

   现在,公司请你帮忙写一个工资管理系统。

   它需要具备一下功能:

1、查询Di目前的工资。

2、为Di加薪x元(-10000000 <= x <= 10000000)。

3、将Di所带领的团队中的每个人,各加薪x元。(Di的所带领的团队表示:Di 及 Di的下属团)

   注意:每个人的初始工资都是0 。

 

输入

   多组测试数据。

   每组测试数据第一行有一个整数n,代表员工数量。(0<n<=100000)。

   接下来n-1行,每行输入两个整数i、j(0<i,j<=n),表示Di的上司是Dj。

   接下来输入一个整数m,代表操作的数量。(0<m<=100000)。

   接下来m行,每行表示一个操作:

1.  输入 Query  i ,表示查询Di的工资。

2.  输入 Add  i  x ,表示将 Di的加薪x元。

3.  输入 All  i  x ,表示将Di带领的团队,每个人加薪x元。

 

输出

    对于操作中的每一个询问,输出相应的答案。

样例输入

4
2 1
3 2
4 2
4
All 1 3
Query 3
Add 3 3
Query 3

样例输出

3
6

 

题目地址:

http://218.194.91.48/acmhome/problemdetail.do?&method=showdetail&id=1440

 

 

这题的方法是 DFS +
树状数组(或者 DFS + 线段树(因为树状数组能做的,线段树都能做么))。。。

 

那么,DFS遍历的过程,主要是为了【树化区间】,大家可以看一下下图:

 

               

 

       转化成区间之后,就是:

 

               

      

像不像将最上面那棵树,往左弯曲?

 

其实,DFS遍历的时候,就是按照 1256791081143,这样的顺序来访问各个节点。

 

于是,我们只需要记录每个节点的[起始点的位置]start,以及能够延伸到的[最远点的位置]end,那么,这个节点以及其所有的子节点,就是[start,end]
这个区间。

 

比如节点1,其区间是[111];节点2的区间[25];节点9的区间[6,9];节11的区间[9,9]

 

 

将树转化成区间之后,那么剩下的就是区间更新、单点查询了(可以参照专题【树状数组】挖坑- 1002)。

 

因此,利用非常基础的树状数组或者线段树,很容易就能解决了。

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

int n,m;

struct Edge{
	int to,next;
}eg[100010];

int Ecnt,Ef[100010],top;

void add_Edge(){
	int a,b;
	scanf("%d%d",&a,&b);
	eg[Ecnt].to=a;
	eg[Ecnt].next=Ef[b];
	Ef[b]=Ecnt++;	
}

int newID,Start[100010],End[100010];

void dfs(int v){
	Start[v]=++newID;
	for(int k=Ef[v];k!=-1;k=eg[k].next){
		dfs(eg[k].to);
	}
	End[v]=newID;
}

__int64 tree[100010];

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

__int64 query(int v){
	__int64 sum=0;
	while(v<=n){
		sum+=tree[v];
		v+=lowbit(v);
	}
	return sum;
}

void update(int v,int val){
	while(v>0){
		tree[v]+=val;
		v-=lowbit(v);
	}
}

void _init(){
	int i;
	Ecnt=0;
	newID=0;
	for(i=1;i<=n;i++){
		Ef[i]=-1;
		tree[i]=0;
		Start[i]=-1;
	}
}

int main(){
	int i,x;
	char op[10];
	while(~scanf("%d",&n)){
		_init();
		for(i=1;i<n;i++)  add_Edge();
		dfs(1);
		scanf("%d",&m);
		while(m--){
			scanf("%s",op);
			if(op[0]=='Q'){
				scanf("%d",&i);
				printf("%I64d\n",query(Start[i]));
			}
			else if(op[1]=='d'){
				scanf("%d%d",&i,&x);
				update(Start[i],x);
				update(Start[i]-1,-x);
			}
			else{
				scanf("%d%d",&i,&x);
				update(End[i],x);
				update(Start[i]-1,-x);
			}
		}
	}
	return 0;
}

 

 

 

抱歉!评论已关闭.