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. 前台js分页,自己手写逻辑

    js代码如下: //设置分页 var pageSize = 10; //设置一次显示多少页 var pageLimit = 5; $(function(){ //查询所有内容 $.post(ctx + ...

  2. 【USACO】clocks 遇到各种问题 最后还是参考别人的思路

    //放在USACO上一直通不过 不知道哪里出了问题 输出的n总是等于1 但是BFS递归的次数是对的 <----这个问题解决了 局部变量压入queue中返回就是对的了 #include<io ...

  3. UVA 11827 Maximum GCD (输入流)

    题目:传送门 题意:求n个数的最大公约数,暴力不会超时,难点在没有个数控制的输入. 题解:用特殊方法输入. #include <iostream> #include <cmath&g ...

  4. Intellj IDEA快捷键

    Alt+回车 导入包,自动修正 Ctrl+N   查找类 Ctrl+Shift+N 查找文件 Ctrl+Alt+L  格式化代码 Ctrl+Alt+O 优化导入的类和包 Alt+Insert 生成代码 ...

  5. 添加Java文档注释

    一.在Eclipse中add javadoc comment的快捷键为: 快捷键为:ALT + SHIFT +J 二.Window-->Preferences-->General--> ...

  6. CSS3 background-size 属性值:cover

    当设置值为cover,可以呈现出图片铺满浏览器内容的视觉效果 实例 规定背景图像的尺寸: div { background:url(img_flwr.gif); background-size:80p ...

  7. 设计模式学习之单例模式(Singleton,创建型模式)(4)

    假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢? 第一步: 新建一个Person类,类中 ...

  8. linux tricks 之 typeof用法.

    typeof是gcc的扩展功能,比较简单,是用来取得参数类型,具体可参考gcc官网的解释. https://gcc.gnu.org/onlinedocs/gcc/Typeof.html ------- ...

  9. 封装了get post方法

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

  10. GDUT 校赛01 dp

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABT8AAAILCAIAAAChHn9YAAAgAElEQVR4nOy9f4il13nneUGgxrRYux ...