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

时间:2022-09-07 15:52:50

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

NBOJv2 1034 Salary Inequity(DFS序+线段树区间更新区间(最值)查询)的更多相关文章

  1. POJ&period;3321 Apple Tree &lpar; DFS序 线段树 单点更新 区间求和&rpar;

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  2. Educational Codeforces Round 6 E dfs序&plus;线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  3. 【BZOJ-3252】攻略 DFS序 &plus; 线段树 &plus; 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  4. Codeforces 343D Water Tree(DFS序 &plus; 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  5. BZOJ2434 &lbrack;Noi2011&rsqb;阿狸的打字机(AC自动机 &plus; fail树 &plus; DFS序 &plus; 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  6. POJ 3321 DFS序&plus;线段树

    单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include &lt ...

  7. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  8. F - Change FZU - 2277 (DFS序&plus;线段树)

    题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...

  9. BZOJ4551&lbrack;Tjoi2016&amp&semi;Heoi2016&rsqb;树——dfs序&plus;线段树&sol;树链剖分&plus;线段树

    题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...

  10. BZOJ1103 &lbrack;POI2007&rsqb;大都市meg dfs序 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...

随机推荐

  1. GJM &colon; 中断被Socket&period;Accept阻塞的线程

    原帖地址:http://blog.csdn.net/kingfox/article/details/7233350 原文作者:狐帝 刚刚学习C#,在编写一个网络通讯的程序的时候,遇到了点麻烦.监听代码 ...

  2. POJ 1144 Network(Tarjan求割点)

    Network Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12707   Accepted: 5835 Descript ...

  3. Activity&lpar;活动&rpar;-再讲

    通过多天的学习,大家也了解了adb.exe 是用来进行 客户端(pc)-服务器端(android) 数据交互的. 用户可以使用工具Eclipse 中DDMS 隐示使用  adb.exe 进行连接,也可 ...

  4. 自签名SSL生成

    本教程以AppServ生成自签名证书为例,同时配置OpenSSL环境1.生成自签名证书,控制台程序进入Apache目录下的bin目录 >openssl req -config ../conf/o ...

  5. ar命令和nm命令(建库!)

    ar 命令详解 今天,跟着我们的技术大牛学了不少东西,首先就是这个ar命令啦. 当我们的程序中有经常使用的模块,而且这些模块在其他程序中也会用到,为了实现代码重用减少软件开发周期,我们可以将它们生成库 ...

  6. EL表达式&lpar;转&rpar;

    转自:http://www.cnblogs.com/Fskjb/archive/2009/07/05/1517192.html EL 全名为Expression Language EL 语法很简单,它 ...

  7. php的set&lowbar;time&lowbar;limit&lpar;&rpar;函数

    set_time_limit(0); 括号里边的数字是执行时间,如果为零说明永久执行直到程序结束,如果为大于零的数字,则不管程序是否执行完成,到了设定的秒数,程序结束. 一个简单的例子,在网页里显示1 ...

  8. c&colon;&bsol;windows&bsol;system32&bsol;config&bsol;systemprofile&bsol;desktop 打不开

    Question 重启开机后显示桌面打不开: 再次重启后无效 Solution 打开注册表regedit如下路径,复制Desktop值到 同路径下的Desktop中,再重启.

  9. springcloud-Ribbon-负载均衡组件

    Ribbon负载均衡 1.Ribbon简介 ribbin是Netflix发布的负载均衡器,有助于控制http和tcp客户端的行为,为ribbon配置服务提供者列表后,ribbon就可以基于某种负载均衡 ...

  10. 第十届Mockplus &squarf; UXPA用户体验西南赛区决赛成功举行

    九月的重庆,秋意渐浓. 伴随着凉爽的秋风,第十届Mockplus·UXPA国际用户体验创新大赛(UXD Award2018)西南赛区决赛于9月16日下午在四川美术学院-虎溪校区成功举办.来自西南区域各 ...