zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",m-n);
    			}
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    Codeforces Round #702 (Div. 3) 题解
    Educational Codeforces Round 104 (Rated for Div. 2) A~E题解
    AtCoder Regular Contest 112 A~D题解
    Codeforces Round #701 (Div. 2) A~E 题解
    java String, StringBuffer, StringBuilder简单介绍和使用
    货仓选址
    线程的同步
    数据结构课设作业
    线程的生命周期(java 图)
    JAVA多线程的创建和使用
  • 原文地址:https://www.cnblogs.com/Blackops/p/5766285.html
Copyright © 2011-2022 走看看