JZOJ5460. 【NOIP2017提高A组冲刺11.7】士兵训练
来源:互联网 发布:淘宝追加的评论不见了 编辑:程序博客网 时间:2024/05/17 20:23
题目
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
题解
观察式子,max(a%b,b%a)=min(a,b)
这个还是比较容易发现的。
先从简单的情况入手,
如果没有请别的人来指导,那就是求子树里面的严格次大值。
min(最大值,次大值)=次大值,这样一定是最大的。
如果有了指导这个操作,题目就没有这么简单了。
从贪心的角度想,
需要有人来指导,那肯定是要获得最大的战斗力。
但是又要注意一个问题,两个人的战斗力不能相同,
因为相同的时候,一取模就变为0了,显然不是最优的。
现在就考虑需要维护些神什么:
1、子树里面的最大值,
2、子树里面的严格次大值,
3、子树里面的严格次次大值,
4、子树里面的次大值,
5、除了这课子树以为,
6、除了这课子树以为,
有了这些信息,每次询问就可以很快地合并这些信息,
从而快速得出答案。
前面4个东西都很好维护,
关键问题还是如何维护后面两个东西。
可以用线段树维护,还有另外一个方法。
再维护子树里面
除了这个子树以为,就可以从除了它父亲以为,以及它父亲的其他儿子转移过来。
code
#include<cstdio>#include<cstring>#include<algorithm>#define N 200003#define P putcharusing namespace std;void read(int &n){ int t=0,p=1;char ch; for(ch=getchar();!('0'<=ch && ch<='9');ch=getchar()) if(ch=='-') p=-1; for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0'; n=t*p;}void write(int x){ if(x>9)write(x/10); P(x%10+48);}int n,q,x,mx1[N],mx2[N],mx3[N],b[N],l[N],f[N],g[N],m1[N],m2[N],w[N];int nxt[N],last[N],ans;void up1(int x,int c){ if(c>mx1[x]) { mx3[x]=mx2[x]; mx2[x]=mx1[x]; w[x]=mx1[x]; mx1[x]=c; return; } if(c<=mx1[x] && c>w[x])w[x]=c; if(c!=mx1[x] && c>mx2[x]) { mx3[x]=mx2[x]; mx2[x]=c; return; } if(c!=mx1[x] && c!=mx2[x] && c>mx3[x])mx3[x]=c;}void up2(int x,int c){ if(c>=m1[x]) { m2[x]=m1[x]; m1[x]=c; return; } if(c>m2[x])m2[x]=c;}void up3(int x,int c){ if(c>f[x]) { g[x]=f[x]; f[x]=c; return; } if(c!=f[x] && c>g[x])g[x]=c;}int max(int x,int y){return x>y?x:y;}int min(int x,int y){if(x==y)return -1;return x<y?x:y;}void dfs(int x){ mx1[x]=b[x]; m1[x]=l[x]; mx2[x]=m2[x]=mx3[x]=0; for(int i=last[x];i;i=nxt[i]) { dfs(i); up1(x,mx1[i]); up1(x,mx2[i]); up1(x,mx3[i]); up1(x,w[i]); up2(x,m1[i]); up2(x,m2[i]); }}void dfs1(int x){ for(int i=last[x];i;i=nxt[i]) { //f[i]=f[x]; up3(i,f[x]); up3(i,g[x]); up3(i,l[x]); for(int j=last[x];j;j=nxt[j]) if(i!=j)up3(i,m1[j]),up3(i,m2[j]); dfs1(i); }}int main(){ freopen("soldier.in","r",stdin); freopen("soldier.out","w",stdout); read(n);read(q); for(int i=2;i<=n;i++) { read(x); nxt[i]=last[x]; last[x]=i; } for(int i=1;i<=n;i++) read(b[i]),read(l[i]); dfs(1); dfs1(1); for(int i=1;i<=q;i++) { read(x); ans=0; ans=max(ans,min(mx1[x],w[x]+f[x])); ans=max(ans,min(mx1[x],w[x]+g[x])); ans=max(ans,min(mx1[x],mx2[x]+f[x])); ans=max(ans,min(mx1[x],mx2[x]+g[x])); ans=max(ans,min(mx1[x],mx3[x]+f[x])); ans=max(ans,min(mx1[x],mx3[x]+g[x])); ans=max(ans,mx2[x]); if(w[x]==0)ans=0; write(ans); P('\n'); } return 0;}
- Jzoj5460【NOIP2017提高A组冲刺11.7】士兵训练
- JZOJ5460. 【NOIP2017提高A组冲刺11.7】士兵训练
- JZOJ 5460. 【NOIP2017提高A组冲刺11.7】士兵训练
- 【NOIP2017提高A组冲刺11.7】总结
- Jzoj5458【NOIP2017提高A组冲刺11.7】质数
- Jzoj5459【NOIP2017提高A组冲刺11.7】密室
- JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室
- JZOJ 5458. 【NOIP2017提高A组冲刺11.7】质数
- JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室
- JZOJ5458. 【NOIP2017提高A组冲刺11.7】质数
- JZOJ5459. 【NOIP2017提高A组冲刺11.7】密室
- 【NOIP2017提高A组冲刺11.1】总结
- 【NOIP2017提高A组冲刺11.2】总结
- 【NOIP2017提高A组冲刺11.3】总结
- 【NOIP2017提高A组冲刺11.4】总结
- 【NOIP2017提高A组冲刺11.1】荒诞
- 【NOIP2017提高A组冲刺11.2】失格
- 【NOIP2017提高A组冲刺11.5】轰炸
- CentOS 7.0 使用 yum 安装 MariaDB 与 MariaDB 的简单配置
- SQL*PLUS登录常见错误
- PAT算法题目 数字分类
- [Unity 优化]CPU优化
- java中的内存分配
- JZOJ5460. 【NOIP2017提高A组冲刺11.7】士兵训练
- 折半枚举(双向搜索)
- 虚树
- mysql5.7的安装参考这两篇文章
- nginx源码阅读(十一).ngx_epoll_module模块(上)
- 去掉字符串当中的连续k个0,Python版
- win10无法访问pv6资源解决办法
- Linux 学习笔记
- html中一些界面设计