zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",max(d,min(v,p+max(m1,m2))));
    				}
    			}
    		}
    	}
    }

  • 相关阅读:
    (转载)openwrt nginx
    *** 竞赛中的各种低级错误,及编程常见错误小结 ***
    信息学奥赛辅导经验谈 & 问题教学法中的学生思维能力培养
    数学&数论的一些题
    信息学竞赛中的一些经典思维 (题)
    从权值线段树到主席树
    浅谈莫队算法
    CSP-S 2019提高组训练 服务器需求
    NOIP2019 PJ 对称二叉树
    NOIP2017 PJ 跳房子 —— 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477226.html
Copyright © 2011-2022 走看看