Jzoj5460【NOIP2017提高A组冲刺11.7】士兵训练

来源:互联网 发布:网络交友的好处 编辑:程序博客网 时间:2024/06/04 04:07

好长一道题结果发现就是个叫你求最大次大的东西

我们跑出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))));}}}}}