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;
}
NBOJv2 1034 Salary Inequity(DFS序+线段树区间更新区间(最值)查询)的更多相关文章
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
- POJ 3321 DFS序+线段树
单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4: 5: #include < ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- F - Change FZU - 2277 (DFS序+线段树)
题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
- BZOJ1103 [POI2007]大都市meg dfs序 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...
随机推荐
- Java中的内存分配机制
Java的内存分为两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型变量和对象的引用都在函数的栈内存中分配.当在一个代码块中定义一个变量的时候,java就在栈中为其分配内存,当超过作用域的 ...
- 两个文件去重的N种姿势
最近利用shell帮公司优化挖掘关键词的流程,用shell替代了多个环节的操作,极大提高了工作效率. shell在文本处理上确有极大优势,比如多文本合并.去重等,但是最近遇到了一个难搞的问题,即两个大 ...
- 为什么内联函数,构造函数,静态成员函数不能为virtual函数
http://blog.csdn.net/freeboy1015/article/details/7635012 为什么内联函数,构造函数,静态成员函数不能为virtual函数? 1> 内联函数 ...
- C#学习笔记-----基于AppDomain的"插件式"开发
很多时候,我们都想使用(开发)USB式(热插拔)的应用,例如,开发一个WinForm应用,并且这个WinForm应用能允许开发人员定制扩展插件,又例如,我们可能维护着一个WinService管理系统, ...
- Tomcat热部署和虚拟目录配置
1.Tomcat如何配置热部署 默认就是 <Host appBase="webapps" autoDeploy="true" name="loc ...
- Vim折叠模式设置
参考文章:http://www.cnblogs.com/welkinwalker/archive/2011/05/30/2063587.html set foldmethod=indent " ...
- Codeigniter:如何写一个好的Model
本文是关于在Code Igniter PHP MVC框架中如何编写Model方法. CRUD 方法 CRUD 是Create, Retrieve, Update, and Delete的缩写. 这些是 ...
- AppPoolService-IIS应用程序池辅助类(C#控制应用程序池操作)
using System.Collections.Generic; using System.DirectoryServices; using System.Linq; using Microsoft ...
- POJ2735/Gym 100650E Reliable Nets dfs
Problem E: Reliable NetsYou’re in charge of designing a campus network between buildings and are ver ...
- 电赛总结(四)——波形发生芯片总结之AD9834
一.特性参数 1.2.3V~5.5V供电 2.输出频率高达37.5MHz 3.正弦波.三角波输出 4.提供相位调制和频率调制功能 5.除非另有说明,VDD = 2.3 V至5.5 V,AGND = D ...