JZOJ 5460. 【NOIP2017提高A组冲刺11.7】士兵训练
Description
Input
第一行两个数n,q 表示士兵数以及阅兵次数。
接下来一行n-1 个整数,第i 个整数表示士兵i+1 的直属教官。
接下来n 行每行两个整数i i b ,l 描述一位士兵的属性。
接下来q 行每行一个整数i s ,表示这次阅兵的总指挥。
Output
对于每次阅兵输出一行一个整数,表示阅兵队伍能展现出的最大精神力P。
Sample Input
输入1:
5 2
1 1 2 2
2 1
1 5
4 2
2 3
3 1
1
2
输入2:
7 3
1 1 2 2 3 3
3 0
1 3
5 2
2 0
4 1
3 1
2 2
1
2
3
Sample Output
输出1:
3
3
样例1 解释:
第一次阅兵时无法进行指导
第二次阅兵时令士兵3 指导士兵4
输出2:
4
3
5
Data Constraint
30%的数据:n,q≤30
另有10%的数据:所有Si 均为1
另有20%的数据:q≤50
另有20%的数据:士兵i 的直属教官为i-1
100%的数据: 1<=n,q<=2*10^5,0<=bi,li<=10^9,bi>=1,1<=Si<=n
Solution
这题的话我们需要处理一个点的子树内的问题,于是我们按照DFS序遍历一遍。
我们发现要使 P 值更大,肯定是让模数越大越好,同时被除数也要变大。
于是我们先考虑不让别的士兵“指导”的情况,那肯定是直接用次大值模最大值。
如果“指导”呢?先找出与答案有关的量:
设子树内b的最大值为 mx 、次大值为 mx1 、严格次大值为 ymx1 、严格第三大值为 ymx2 。
再设子树外 ll 的最大值为 x ,严格次大值为 y 。
如果有 mx1+x<mxmx1+x ,则答案就是 mx1+xmx1+x (直接提升次大值)。
如果有 mx1+x>mxmx1+x>mx ,则答案就为 mxmx (仍然直接提升次大值并当作模数)。
如果有 mx1+x=mxmx1+x=mx ,那么还要继续讨论:
取 mx1+ymx1+y
取 ymx2+xymx2+x
取 ymx1ymx1
将以上情况取最大值即可,上述的每个量都可以用线段树维护,
因为 DFS 序一定是连续的一段(非常繁杂~~~)。
注意若查询的点是叶子结点( size 为 1),那么要特判输出 0,因为自己模自己为 0 。
Code
#include<cstdio>
using namespace std;
const int N=2e5+1;
struct tree
{int mx,mx1,ymx1,ymx2;
}f[N<<2];
struct data
{int x,y;
}a[N],g[N<<2],null;
int tot;
int first[N],next[N],en[N];
int dfn[N],size[N],pre[N];
inline int read()
{int X=0,w=1; char ch=0;while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*w;
}
inline void write(int x)
{if(x>9) write(x/10);putchar(x%10+'0');
}
inline int max(int x,int y)
{return x>y?x:y;
}
inline int min(int x,int y)
{return x<y?x:y;
}
inline void insert(int x,int y)
{next[++tot]=first[x];first[x]=tot;en[tot]=y;
}
inline void dfs(int x)
{size[x]=1;dfn[x]=++tot;pre[tot]=x;for(int i=first[x];i;i=next[i]){dfs(en[i]);size[x]+=size[en[i]];}
}
inline tree mergef(tree x,tree y)
{tree z;if(x.mx>y.mx){z.mx=x.mx;z.mx1=max(y.mx,x.mx1);z.ymx1=max(y.mx,x.ymx1);z.ymx2=x.ymx2;if(x.ymx1>y.mx) z.ymx2=max(z.ymx2,y.mx);if(x.ymx1<y.mx) z.ymx2=max(z.ymx2,max(x.ymx1,y.ymx1));if(x.ymx1==y.mx) z.ymx2=max(z.ymx2,y.ymx1);}elseif(x.mx<y.mx){z.mx=y.mx;z.mx1=max(x.mx,y.mx1);z.ymx1=max(x.mx,y.ymx1);z.ymx2=y.ymx2;if(y.ymx1>x.mx) z.ymx2=max(z.ymx2,x.mx);if(y.ymx1<x.mx) z.ymx2=max(z.ymx2,max(y.ymx1,x.ymx1));if(y.ymx1==x.mx) z.ymx2=max(z.ymx2,x.ymx1);}else{z.mx=z.mx1=x.mx;z.ymx1=max(x.ymx1,y.ymx1);if(x.ymx1^y.ymx1) z.ymx2=max(x.ymx2,y.ymx2); elsez.ymx2=min(x.ymx1,y.ymx1);}return z;
}
inline data mergeg(data x,data y)
{data z;if(x.x>y.x){z.x=x.x;z.y=max(y.x,x.y);}elseif(x.x<y.x){z.x=y.x;z.y=max(x.x,y.y);}else{z.x=x.x;z.y=max(x.y,y.y);}return z;
}
inline void make(int v,int l,int r)
{if(l==r){f[v].mx=a[pre[l]].x;g[v].x=a[pre[l]].y;return;}int mid=(l+r)>>1,ls=v<<1l,rs=ls|1;make(ls,l,mid);make(rs,mid+1,r);f[v]=mergef(f[ls],f[rs]);g[v]=mergeg(g[ls],g[rs]);
}
inline tree findf(int v,int l,int r,int x,int y)
{if(l>=x && r<=y) return f[v];int mid=(l+r)>>1;if(y<=mid) return findf(v<<1,l,mid,x,y);if(x>mid) return findf(v<<1|1,mid+1,r,x,y);return mergef(findf(v<<1,l,mid,x,mid),findf(v<<1|1,mid+1,r,mid+1,y));
}
inline data findg(int v,int l,int r,int x,int y)
{if(x>y) return null;if(l>=x && r<=y) return g[v];int mid=(l+r)>>1;if(y<=mid) return findg(v<<1,l,mid,x,y);if(x>mid) return findg(v<<1|1,mid+1,r,x,y);return mergeg(findg(v<<1,l,mid,x,mid),findg(v<<1|1,mid+1,r,mid+1,y));
}
int main()
{int n=read(),q=read();for(int i=2;i<=n;i++) insert(read(),i);for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();tot=0,dfs(1);make(1,1,n);while(q--){int s=read(),ans=0;if(size[s]==1){puts("0");continue;}tree tx=findf(1,1,n,dfn[s],dfn[s]+size[s]-1);data ty=mergeg(findg(1,1,n,1,dfn[s]-1),findg(1,1,n,dfn[s]+size[s],n));if(tx.mx1+ty.x<tx.mx) ans=tx.mx1+ty.x; elseif(tx.mx1+ty.x>tx.mx) ans=tx.mx; else{if(tx.mx1 && ty.y) ans=tx.mx1+ty.y;if(tx.ymx2 && ty.x) ans=max(ans,tx.ymx2+ty.x);if(tx.ymx1) ans=max(ans,tx.ymx1);}write(ans),putchar('\n');}return 0;
}
JZOJ 5460. 【NOIP2017提高A组冲刺11.7】士兵训练相关推荐
- JZOJ 5441. 【NOIP2017提高A组冲刺11.1】序列
Description 给定一个1~n的排列x,每次你可以将x1~xi翻转.你需要求出将序列变为升序的最小操作次数.有多组数据. Input 第一行一个整数t表示数据组数. 每组数据第一行一个整数n, ...
- JZOJ 5458. 【NOIP2017提高A组冲刺11.7】质数
Description 小X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小X 认为,质数是一切自然数起源的地方. 在小X 的认知里,质数是除了本身和1 以外,没有其他因数的数 ...
- JZOJ 5455. 【NOIP2017提高A组冲刺11.6】拆网线
Description 企鹅国的网吧们之间由网线互相连接,形成一棵树的结构.现在由于冬天到了,供暖部门缺少燃料,于是他们决定去拆一些网线来做燃料.但是现在有K只企鹅要上网和别人联机游戏,所以他们需要把 ...
- JZOJ 5445. 【NOIP2017提高A组冲刺11.2】失格
Description 胆小鬼连幸福都会害怕,碰到棉花都会受伤,有时还被幸福所伤. --太宰治<人间失格> 回顾我的一生,一共有n个事件,每一个事件有一个幸福值p_i. 我想用n-1条线把 ...
- JZOJ 5466. 【NOIP2017提高A组冲刺11.9】玩游戏
Description 小A得了忧郁综合症,小B正在想办法开导她. 机智的小B决定陪着小A玩游戏,他从魔法的世界里变出一张无向联通图,每条边上都有边权.小B定义一条路径的权值为所有经过边中的最大权值, ...
- JZOJ 5462. 【NOIP2017提高A组冲刺11.8】好文章
Description nodgd写了一篇文章,自认为这是一篇好文章.nodgd的文章由n个小写英文字母组成.文章的一个子串指的是文章中的一段连续的字母,子串的长度就是这一段的字母个数.nodgd在文 ...
- JZOJ 5463. 【NOIP2017提高A组冲刺11.8】证书
Description Pulumi生活在P城的角落,而他的朋友们gjdy,oyski,tutuwai等等生活在P城的靠中心位置. P城很大,但它拥有优秀的城市结构,同时P城重视文化教育的发展,P城共 ...
- JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室
Description 小X 正困在一个密室里,他希望尽快逃出密室. 密室中有N 个房间,初始时,小X 在1 号房间,而出口在N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会 ...
- JZOJ 5454. 【NOIP2017提高A组冲刺11.5】仔细的检查
Description nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上.另一天nodgd更无聊,就又画了一张. 这时nodgd发现,两次画的顺序是不一样的,这就导致了原本 ...
最新文章
- 读样章、写评语,即有机会获赠《编程大师访谈录》!
- graphic头文件函数_graphics.h头文件详解
- 2021 年4月数据库流行度排行榜出炉!Snowflake 和 Clickhouse上升迅速!
- NYOJ 875 小M的操作数
- OpenCASCADE:函数机制的使用
- 每天一个linux命令(58):telnet命令
- VB.NET 开发ColorPicker例子
- OneNote中到底能放多少种东西?
- 推理集 —— 特殊与差异
- 如何使用CineMatch的伪色指南功能来帮助评估图像
- 《java就业培训教程》读书笔记
- Objective-C 函数(方法)的定义和调用
- matlab 矩阵模二运算符,MATLAB中怎样进行模二加的运算?
- 王一博、肖战、吴宣仪、杨紫,2019明星沸点榜,谁的颜值更高,Python告诉你
- 去除Edge打开外部应用时的提醒
- winxp网络找不到计算机,WinXP系统电脑打开WiFi搜索不到无线网络的解决方法
- 让电脑自动开机、关机以及取消开机密码
- 如何将视频轻松转换为 GIF
- java 编配和弦_六个和弦编配小诀窍,让你的弹唱伴奏丰富好听
- STM32使用串口1配合DMA接收不定长数据,大大减轻CPU载荷。