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

Jzoj5460【NOIP2017提高A组冲刺11.7】士兵训练_第1张图片

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

我们跑出dfs序和主席树后,开始分类讨论

1.只有一个节点

2.有不止两个最大值,且在此子树外有l[i]不为0的节点

3.只有一个最大值,而次大值+子树外l[i]的最大值不等于最大值

4.只有一个最大值,而次大值+子树外l[i]的最大值等于最大值,就取第三大值和最大值相加,和次大值和子树外次大值相加

(这里的次大和第三大都是严格的)

主席树框架是写对了,但是main函数里面各种傻逼错误。。。。。

而且这题还卡栈,必须开个O3

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include
#include
#include
#include
#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;ivoid 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))));
				}
			}
		}
	}
}

你可能感兴趣的:(OI,数据结构,----线段树,--------可持久化线段树,----树链剖分/dfs序,Jzoj)