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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章