Jzoj5460【NOIP2017提高A组冲刺11.7】士兵训练
好长一道题结果发现就是个叫你求最大次大的东西
我们跑出dfs序和主席树后,开始分类讨论
1.只有一个节点
2.有不止两个最大值,且在此子树外有l[i]不为0的节点
3.只有一个最大值,而次大值+子树外l[i]的最大值不等于最大值
4.只有一个最大值,而次大值+子树外l[i]的最大值等于最大值,就取第三大值和最大值相加,和次大值和子树外次大值相加
(这里的次大和第三大都是严格的)
主席树框架是写对了,但是main函数里面各种傻逼错误。。。。。
而且这题还卡栈,必须开个O3
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 200010
#define M 1000000000
#define mid (l+r>>1)
using namespace std;
struct tree{ int l,r,s; } s[20000010];
int n,m,cnt=0,l[N],r[N],rt[N];
int clk=0,b[N],v[N],w[N],rt2[N],w2[N];
vector<int> G[N];
void dfs(int x){
l[x]=++clk;
for(int i=0;i<G[x].size();++i) dfs(G[x][i]);
r[x]=clk;
}
void insert(int l,int r,int r1,int& r2,int k){
if(!r2) r2=++cnt; s[r2].s=s[r1].s+1;
if(l==r) return;
if(k<=mid){ s[r2].r=s[r1].r; insert(l,mid,s[r1].l,s[r2].l,k); }
else { s[r2].l=s[r1].l; insert(mid+1,r,s[r1].r,s[r2].r,k); }
}
int fdmx(int l,int r,int r1,int r2,int& cnt){
if(s[r2].s-s[r1].s<=0) return cnt=0;
if(l==r){ cnt=s[r2].s-s[r1].s; return l; }
if(s[s[r2].r].s-s[s[r1].r].s) return fdmx(mid+1,r,s[r1].r,s[r2].r,cnt);
else return fdmx(l,mid,s[r1].l,s[r2].l,cnt);
}
int gpre(int l,int r,int r1,int r2,int k,int& cnt){
if(l==r) return k;
if(k<=mid) return gpre(l,mid,s[r1].l,s[r2].l,k,cnt);
else {
int p=gpre(mid+1,r,s[r1].r,s[r2].r,k,cnt);
if(p==k){
int v=fdmx(l,mid,s[r1].l,s[r2].l,cnt);
if(cnt) return v; else return k;
}
return p;
}
}
int main(){
freopen("soldier.in","r",stdin);
freopen("soldier.out","w",stdout);
scanf("%d%d",&n,&m);
for(int x,i=2;i<=n;++i){
scanf("%d",&x);
G[x].push_back(i);
}
dfs(1);
for(int i=1;i<=n;++i){
scanf("%d%d",b+i,v+i);
w[l[i]]=b[i]; w2[l[i]]=v[i];
}
for(int i=1;i<=n;++i) if(w[i]) insert(1,M,rt[i-1],rt[i],w[i]); else rt[i]=rt[i-1];
for(int i=1;i<=n;++i) if(w2[i]) insert(1,M,rt2[i-1],rt2[i],w2[i]); else rt2[i]=rt2[i-1];
for(int x;m--;){
scanf("%d",&x);
int c,v=fdmx(1,M,rt[l[x]-1],rt[r[x]],c);
int c1,c2,m1,m2,d,p,_c;
m1=fdmx(1,M,rt2[0],rt2[l[x]-1],c1);
m2=fdmx(1,M,rt2[r[x]],rt2[n],c2);
m1*=(bool)c1; m2*=(bool)c2;
if(c>1 && (c1||c2)) printf("%d\n",v);
else {
m1*=(bool)c1; m2*=(bool)c2;
p=gpre(1,M,rt[l[x]-1],rt[r[x]],v,_c);
d=max(m1,m2);
if(!_c||p==v) puts("0");
else{
if(p+d!=v) printf("%d\n",min(v,p+d));
else{
d+=gpre(1,M,rt[l[x]-1],rt[r[x]],p,c); if(!c) d=0;
if(p+m1==v) m1=gpre(1,M,rt2[0],rt2[l[x]-1],m1,c1);
if(p+m2==v) m2=gpre(1,M,rt2[r[x]],rt2[n],m2,c2);
m1*=(bool)c1; m2*=(bool)c2;
printf("%d\n",max(d,min(v,p+max(m1,m2))));
}
}
}
}
}