zoukankan      html  css  js  c++  java
  • 节点树xmu 1466.祖先极值

    首先声明,我是一个菜鸟。一下文章中出现技术误导情况盖不负责

        

    1466.先人极值
    Time Limit: 5000 MS Memory Limit: 131072 K
    Total Submissions: 153 (39 users) Accepted: 43 (25 users)
    [ My Solution]

        

    Description

        

    在一棵有向树中, 若节点u至节点v之间有一条有向边, 则我们称u为v的父节点, 也可以称作1先人节点。所谓节点v的k先人节点, 指的是节点v的父节点的k-1先人节点。当初, 给定你一棵以0为根节点的树, 树上的每一个节点都有一个值, 你需要能快速的回答出从节点v至它的k先人节点所经过的全部节点中(即v节点、v节点的1先人、...、v节点的k-1先人、v节点的k先人), 值最大的节点的值的为多少? 其中我们默认0号节点的值为0。

        

    Input

        

    输入的第一行有一个正整数n (n <= 100,000), 接下来的一行有n个整数ai(1 <= i <= n, 1 <= ai <= 1,000,000,000), 第i个数字代表了第i号节点上的数值。再接下来的一行有n个正整数bi(1 <= i <= n, 0 <= bi < i), 第i个数字代表了第i号节点的父节点的为bi。再接下来有一个整数m (1 <= m <= 100,000), 代表了询问的次数, 接下来的m行, 每行有2个整数k, v (1 <= k <= n, 1 <= v <= n), 代表了询问, 从v节点到它的k先人所阅历的全部节点中的最大值。

        

    Output

        

    对于每次询问, 若v节点不存在k先人, 则输出一行"Wrong request", 否则输出一个整数, 代表了从v节点到它的k先人所阅历的全部节点中的最大值。

        

    Sample Input

        

    5
    1 2 2 1 3
    0 0 1 1 2
    4
    1 4
    2 2
    2 3
    1 5

        

    Sample Output

        

    1
    Wrong request
    2
    3

        

    唉,我真是太笨了,看了别人的代码才会做,就是以树的高度作为区间查询

        

    妹的,苦逼的调试
        每日一道理
    时间好比一条小溪,它能招引我们奔向生活的海洋;时间如同一叶扁舟,它将帮助我们驶向理想的彼岸;时间犹如一支画笔,它会指点我们描绘人生的画卷。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define N 100010
    #define l(i)  i<<1
    #define r(i)  i<<1|1
    struct node{
    	int l,r,mx;
    }T[N*4];
    int mx;
    struct Data{
    	int x,id;
    };
    int v[N],ans[N];//值,答案
    vector<Data>a[N];
    vector<int>son[N];
    void build(int l,int r,int k){
    	T[k].l=l;
    	T[k].r=r;
    	T[k].mx=0;
    	if(l==r)return;
    	int mid=(l+r)/2;
    	build(l,mid,l(k));
    	build(mid+1,r,r(k));
    }
    int insert(int d,int k,int v){//值k插入区间[d,d]
    	if(T[k].l==T[k].r)return T[k].mx=v;
    	int ll=l(k);
    	int rr=r(k);
    	if(T[ll].r>=d)insert(d,ll,v);//往左
    	else if(T[rr].l<=d) insert(d,rr,v);//往右
    	return T[k].mx=max(T[ll].mx,T[rr].mx);
    }
    void query(int l,int r,int k){//查询区间[l,r]
    	if(T[k].l==l&&T[k].r==r){
    		mx=max(mx,T[k].mx);
    		return;
    	}
    	int ll=l(k);
    	int rr=r(k);
    	if(T[ll].r>=r)query(l,r,ll);//往左
    	else if(T[rr].l<=l)query(l,r,rr);//往右
    	else{
    		query(l,T[ll].r,ll);//往左
    		query(T[rr].l,r,rr);//往右
    	}
    }
    void dfs(int x,int d){
    	int i,j,k;
    	insert(d,1,v[x]);//插入v
    	//cout<<"插入"<<x<<" "<<v[x]<<endl;
    	for(i=0;i<a[x].size();i++){//查询x结点
    		k=d-a[x][i].x;
    		mx=-1;
    		if(k>=0)query(k,d,1);
    		ans[a[x][i].id]=mx;
    		//cout<<x<<" "<<k<<" "<<d<<" "<<mx<<endl;
    	}
    	for(i=0;i<son[x].size();i++)//遍历儿子
    		dfs(son[x][i],d+1);//递归遍历
    }
    int main(){
    	int n,i,j,k;
    	v[0]=0;
    	struct Data s;
    	while(scanf("%d",&n)!=EOF){
    		memset(a,0,sizeof(a));
    		memset(son,0,sizeof(son));
    		build(0,n-1,1);//建立空树
    		for(i=1;i<=n;i++)scanf("%d",&v[i]);
    		for(i=1;i<=n;i++){
    			scanf("%d",&j);
    			son[j].push_back(i);//i是j的儿子
    		}
    		scanf("%d",&n);
    		for(i=0;i<n;i++){
    			scanf("%d%d",&j,&k);
    			s.x=j;s.id=i;
    			a[k].push_back(s);
    		}
    		/*for(i=0;i<=n;i++){
    			cout<<i<<":";
    			for(j=0;j<son[i].size();j++){
    				cout<<son[i][j]<<" ";
    			}
    			cout<<endl;
    		}*/
    		dfs(0,0);//从根遍历到最后
    		for(i=0;i<n;i++)
    			if(ans[i]==-1)printf("Wrong request\n");
    				else printf("%d\n",ans[i]);
    	}
    return 0;
    }

    文章结束给大家分享下程序员的一些笑话语录: 腾讯的动作好快,2010年3月5日19时28分58秒,QQ同时在线人数1亿!刚刚看到编辑发布的文章,相差才2分钟,然后连专题页面都做出来了,他们早就预料到了吧?(其实,每人赠送10Q币,轻轻松松上两亿!)

  • 相关阅读:
    【转载】产品经理如何行之有效的提高执行力
    【转载】20个2013年最值得关注的网页设计趋势
    【转载】HTTP协议详解
    工作一年的心得与体会
    【转载】什么是SVG
    【ul开发攻略】HTML5/CSS3菜单代码 阴影+发光+圆角
    【转载】前台页面优化全攻略-系列博文
    flink的checkpoint
    HBase概述
    牛客题霸--跳台阶题解
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3084566.html
Copyright © 2011-2022 走看看