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.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

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

  2. Educational Codeforces Round 6 E dfs序+线段树

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

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

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

  4. Codeforces 343D Water Tree(DFS序 + 线段树)

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

  5. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

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

  6. POJ 3321 DFS序+线段树

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

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

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

  8. F - Change FZU - 2277 (DFS序+线段树)

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

  9. BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树

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

  10. BZOJ1103 [POI2007]大都市meg dfs序 线段树

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

随机推荐

  1. SQLHelper、DBUtil终极封装

    DBUtil.java package org.guangsoft.util; import java.io.InputStream; import java.sql.Connection; impo ...

  2. 一个程序中关于多个osgGA::GUIEventHandler同时存在的问题

    平时使用GUIEventHandler不太注意handle()函数的返回值,觉得返回true或者false都无所谓,其实不然. 我遇到的问题是程序中一个节点添加了GUIEventHandler对象pi ...

  3. 解决 mysql 启动报错--发现系统错误2,系统找不到指定的文件

    HKEY_LOCAL_MACHINE-SYSTEM-CurrentControlSet-services-mysql(服务名)-ImagePath 更改为(自己的):"C:\Program ...

  4. 重命名nginx服务器

    为了防止被黑客扫描到web服务器信息,通过相对应的web服务器信息找出对应的版本漏洞,从而对web服务器进行入侵,nginx虽然功能强大,但是也是软件,软件就可能会有漏洞,例如nginx-0.6.32 ...

  5. struts2 标签问题----日期显示

    对于要显示按照自己的意愿进行显示的话: <s:date name="date" format="yyyy-MM-dd HH:mm:ss.SSS" /> ...

  6. hdu 4666:Hyperspace(最远曼哈顿距离 + STL使用)

    Hyperspace Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Tota ...

  7. oracle11g客户端 安装图解

    软件位置:我的网盘 -- oracle空间 -- oracle工具 -- win64_11gR2_database_clint(客户端) -- 压缩软件包 先将下载下来的ZIP文件解压,并运行setu ...

  8. 封装了get post方法

    function g($name, $defaultValue = "") { // php这里区分大小写,将两者都变为小写 $_GET = array_change_key_ca ...

  9. 小甲鱼PE详解之区块描述、对齐值以及RVA详解(PE详解06)

    各种区块的描述: 很多朋友喜欢听小甲鱼的PE详解,因为他们觉得课堂上老师讲解的都是略略带过,绕得大家云里雾里~刚好小甲鱼文采也没课堂上的教授讲的那么好,只能以比较通俗的话语来给大家描述~ 通常,区块中 ...

  10. 电赛总结(四)——波形发生芯片总结之AD9834

    一.特性参数 1.2.3V~5.5V供电 2.输出频率高达37.5MHz 3.正弦波.三角波输出 4.提供相位调制和频率调制功能 5.除非另有说明,VDD = 2.3 V至5.5 V,AGND = D ...