NBOJv2 1034 Salary Inequity(DFS序+线段树区间更新区间(最值)查询)

 

Problem 1034: Salary Inequity

 

Time Limits:  10000 MS   Memory Limits:  200000 KB

64-bit interger IO format:  %lld   Java class name:  Main


Description

There is a large company of N employees. With the exception of one employee, everyone has a direct supervisor. The employee with no direct supervisor is indirectly a supervisor of all other employees in the company. We say that employee X is a subordinate of employee Y if either Y is the direct supervisor of X, or the direct supervisor of X is a subordinate of Y .

One day, the HR department decides that it wants to investigate how much inequity there is in the company with respect to salaries. For a given employee, the inequity of the employee is the difference between the minimum salary of that employee and all his/her subordinates and the maximum salary of that employee and all his/her subordinates.

HR wants to be able to compute the inequity for any employee quickly. However, this is complicated by the fact that an employee will sometimes give himself/herself, along with all his/her subordinates, a raise. Can you help? 

Input

The first line of your input file contains a number T representing the number of companies you will be analyzing for inequity. T will be at most 20.

For each company, there will be a line containing an integer N, representing the number of employees at the company. Each employee is assigned an ID which is a unique integer from 1 to N. The next line will contain N − 1 integers. The Kth integer in that line is the ID of the direct supervisor of employee (K + 1). The next line will contain N integers, the Kth integer in this line being the salary of employee K. The next line contains an integer Q, the number of events that you will need to process. There are two types of events to process - raises and inequity queries. In the event of a raise, the line will start with the letter R followed by the ID of the employee and an integer representing the increase in salary for that employee and all his/her subordinates. In the event of an inequity query, the line will start with the letter Q followed by the ID of the employee for whom inequity needs to be determined.

2 <= N <= 1,000,000
1 <= Q <= 10,000
For every employee K, the ID of his/her supervisor will be less than K. Initial salaries will

range from 1 to 1,000. No raise will exceed 1,000.

Output

For each inequity query, print the inequity of the employee on its own line. 

Sample Input

1
5
1 1 2 2
10 6 8 4 5 7
Q 2
Q 3
R 4 2
Q 2
Q 1
R 2 4
Q 1

Output for Sample Input

2
0
1
5
2

 

 

线段树是对于连续的区间操作,但是如果是一棵树,显然是仅符合线段树思想但并不连续,DFS标号构造一个序列,然后再用线段树处理……好题……,输入外挂优化后200MS+,一开始pushdown时左右子树的add忘记加了WA几次…

代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=1000010;
int total,in[N],OUT[N];
int arr[N];
int n;
int ref[N];
int head[N],cnt;
struct info
{
	int to;
	int pre;
}E[N<<1];
struct seg
{
	int l,mid,r;
	int maxm,minm,add;
};
seg T[N<<2];
void add(int s,int t)
{
	E[cnt].to=t;
	E[cnt].pre=head[s];
	head[s]=cnt++;
}
void dfs(int now,int fa)
{
	in[now]=++total;
	ref[total]=now;
	for (int i=head[now]; ~i; i=E[i].pre)
	{
		int v=E[i].to;
		if(v!=fa)	
			dfs(v,now);
	}
	OUT[now]=total;
}
void init()
{
	total=0;
	MM(in,0);
	MM(OUT,0);
	MM(arr,0);
	MM(ref,0);
	MM(head,-1);
	cnt=0;
}
void pushup(int k)
{
	T[k].maxm=max(T[LC(k)].maxm,T[RC(k)].maxm);
	T[k].minm=min(T[LC(k)].minm,T[RC(k)].minm);
}
void pushdown(int k)
{
	if(T[k].add)
	{
		T[LC(k)].add+=T[k].add;
		T[RC(k)].add+=T[k].add;
		T[LC(k)].maxm+=T[k].add;
		T[RC(k)].maxm+=T[k].add;
		T[LC(k)].minm+=T[k].add;
		T[RC(k)].minm+=T[k].add;
		T[k].add=0;
	}	
}
void build(int k,int l,int r)
{
	T[k].l=l;
	T[k].r=r;
	T[k].mid=MID(l,r);
	T[k].add=T[k].maxm=T[k].minm=0;
	if(l==r)
	{
		T[k].maxm=T[k].minm=arr[ref[l]];//初值的处理
		return ;
	}		
	build(LC(k),l,T[k].mid);
	build(RC(k),T[k].mid+1,r);
	pushup(k);
}
void update(int k,int l,int r,int val)
{
	if(r<T[k].l||l>T[k].r)
		return ;
	if(l<=T[k].l&&r>=T[k].r)
	{
		T[k].add+=val;
		T[k].maxm+=val;
		T[k].minm+=val;
	}
	else
	{
		pushdown(k);
		update(LC(k),l,r,val);
		update(RC(k),l,r,val);
		pushup(k);
	}
}
int mmquery(int k,int l,int r)
{
	if(l<=T[k].l&&r>=T[k].r)
		return T[k].maxm;
	pushdown(k);
	if(r<=T[k].mid)
		return mmquery(LC(k),l,r);
	else if(l>T[k].mid)
		return mmquery(RC(k),l,r);
	else
		return max(mmquery(LC(k),l,T[k].mid),mmquery(RC(k),T[k].mid+1,r));
}
int mnquery(int k,int l,int r)
{
	if(l<=T[k].l&&r>=T[k].r)
		return T[k].minm;
	pushdown(k);
	if(r<=T[k].mid)
		return mnquery(LC(k),l,r);
	else if(l>T[k].mid)
		return mnquery(RC(k),l,r);
	else
		return min(mnquery(LC(k),l,T[k].mid),mnquery(RC(k),T[k].mid+1,r));
}
int Scan()
{
    int res=0,ch,flag=0;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
int main(void)
{
	int tcase, i, x, q, val;
	char ops[3];
	scanf("%d",&tcase);
	while (tcase--)
	{
		init();
		scanf("%d",&n);
		for (i=1; i<n; ++i)
		{
			x=Scan();
			add(x,i+1);
		}
		for (i=1; i<=n; ++i)
			arr[i]=Scan();
		dfs(1,-1);
		build(1,1,n);
		scanf("%d",&q);
		while (q--)
		{
			scanf("%s",ops);
			if(ops[0]=='R')
			{
				scanf("%d%d",&x,&val);
				update(1,in[x],OUT[x],val);
			}
			else
			{
				scanf("%d",&x);
				int m=mmquery(1,in[x],OUT[x]),n=mnquery(1,in[x],OUT[x]);
				printf("%d\n",m-n);
			}
		}
	}
	return 0;
}

另一种写法:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=1000010;
struct info
{
	int to;
	int pre;
}E[N];
int head[N],cnt;
int total,in[N],out[N];
int arr[N];
int n;
struct seg
{
	int l,mid,r;
	int maxm,minm,add;
};
seg T[N<<2];
void add(int s,int t)
{
	E[cnt].to=t;
	E[cnt].pre=head[s];
	head[s]=cnt++;
}
void dfs(int now,int fa)
{
	in[now]=++total;	
	for (int i=head[now]; ~i; i=E[i].pre)
	{
		int v=E[i].to;
		if(v!=fa)	
			dfs(v,now);
	}
	out[now]=total;
}
void init()
{
	MM(head,-1);
	cnt=0;
	total=0;
	MM(in,0);
	MM(out,0);
	MM(arr,0);
}
void pushup(int k)
{
	T[k].maxm=max(T[LC(k)].maxm,T[RC(k)].maxm);
	T[k].minm=min(T[LC(k)].minm,T[RC(k)].minm);
}
void pushdown(int k)
{
	if(!T[k].add)
		return ;
	T[LC(k)].add+=T[k].add;
	T[RC(k)].add+=T[k].add;
	T[LC(k)].maxm+=T[k].add;
	T[RC(k)].maxm+=T[k].add;
	T[LC(k)].minm+=T[k].add;
	T[RC(k)].minm+=T[k].add;
	T[k].add=0;
}
void build(int k,int l,int r)
{
	T[k].l=l;
	T[k].r=r;
	T[k].mid=MID(l,r);
	T[k].add=T[k].maxm=T[k].minm=0;
	if(l==r)
		return ;
	build(LC(k),l,T[k].mid);
	build(RC(k),T[k].mid+1,r);
}
void update(int k,int l,int r,int val)
{
	if(r<T[k].l||l>T[k].r)
		return ;
	if(l<=T[k].l&&r>=T[k].r)
	{
		T[k].add+=val;
		T[k].maxm+=val;
		T[k].minm+=val;
	}
	else
	{
		pushdown(k);
		update(LC(k),l,r,val);
		update(RC(k),l,r,val);
		pushup(k);
	}
}
int mmquery(int k,int l,int r)
{
	if(l<=T[k].l&&r>=T[k].r)
		return T[k].maxm;
	pushdown(k);
	if(r<=T[k].mid)
		return mmquery(LC(k),l,r);
	else if(l>T[k].mid)
		return mmquery(RC(k),l,r);
	else
		return max(mmquery(LC(k),l,T[k].mid),mmquery(RC(k),T[k].mid+1,r));
}
int mnquery(int k,int l,int r)
{
	if(l<=T[k].l&&r>=T[k].r)
		return T[k].minm;
	pushdown(k);
	if(r<=T[k].mid)
		return mnquery(LC(k),l,r);
	else if(l>T[k].mid)
		return mnquery(RC(k),l,r);
	else
		return min(mnquery(LC(k),l,T[k].mid),mnquery(RC(k),T[k].mid+1,r));
}
int main(void)
{
	int tcase, i, j, x, y, q, val;
	char ops[3];
	scanf("%d",&tcase);
	while (tcase--)
	{
		init();
		scanf("%d",&n);
		for (i=1; i<n; ++i)
		{
			scanf("%d",&x);
			y=i+1;
			add(x,y);
		}
		for (i=1; i<=n; ++i)
			scanf("%d",&arr[i]);
		dfs(1,-1);
		build(1,1,n);
		for (i=1; i<=n; ++i)
			update(1,in[i],in[i],arr[i]);//对于初值的处理
		scanf("%d",&q);
		while (q--)
		{
			scanf("%s",ops);
			if(ops[0]=='R')
			{
				scanf("%d%d",&x,&val);
				update(1,in[x],out[x],val);
			}
			else
			{
				scanf("%d",&x);
				int m=mmquery(1,in[x],out[x]),n=mnquery(1,in[x],out[x]);
				printf("%d\n",m-n);
			}
		}
	}
	return 0;
}

转载于:https://www.cnblogs.com/Blackops/p/5766285.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值