hihocoder#1576 : 子树中的最小权值(dfs序+线段树)

来源:互联网 发布:微信公众号域名是什么 编辑:程序博客网 时间:2024/06/05 03:06

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

给定一棵N个节点的树,编号1~N。其中1号节点是根,并且第i个节点的权值是Vi

针对这棵树,小Hi会询问小Ho一系列问题。每次小Hi会指定一个节点x,询问小Ho以x为根的子树中,最小的权值是多少。为了增加难度,小Hi可能随时改变其中每个节点的权值。

你能帮助小Ho准确、快速的回答小Hi的问题吗?

输入

第一行一个正整数N。

第二行N个整数,V1, V2, ... VN

第三行n-1个正整数,第i个数Pi表示第i+1号节点的父结点是第Pi号节点。注意1号节点是根。

第四行一个正整数Q,表示有Q个询问/修改权值。

接下来Q行,每行可能有如下两种输入格式:

1 x u

2 x

第一种表示将第x号节点的权值修改为u

第二种表示询问以第x号节点为根的子树中,最小的权值是多少。

对于30%的数据,1 ≤ N, Q ≤ 1000  

对于100%的数据,1 ≤ N, Q ≤ 100000, -109 <= Vi, u <= 109  

输出

对于每次询问,输出一个整数表示答案。

样例输入
123 5 -1 -2 9 6 2 8 -10 11 8 101 1 1 2 4 2 6 7 7 8 8102 32 12 61 11 -51 5 -122 62 42 22 12 7
样例输出
-1-106-5-5 -12-12-10
思路:dfs序+线段树。

#include<bits/stdc++.h>using namespace std;const int MAX=1e6+10;struct lenka{    int ans,l,r;}a[MAX<<2];vector<int>e[MAX];int L[MAX],R[MAX],num[MAX];int tot=0,A[MAX];void dfs(int k){    L[k]=++tot;    num[tot]=A[k];    for(int i=0;i<e[k].size();i++)    {        int nex=e[k][i];        dfs(nex);    }    R[k]=tot;}void build(int k,int l,int r){    a[k].l=l,a[k].r=r;    if(l==r){a[k].ans=num[l];return;}    build(2*k,l,(l+r)/2);    build(2*k+1,(l+r)/2+1,r);    a[k].ans=min(a[2*k].ans,a[2*k+1].ans);}void change(int k,int x,int tag){    if(a[k].l==x&&a[k].r==x)    {        a[k].ans=tag;        return;    }    if(x<=a[2*k].r)change(2*k,x,tag);    if(x>=a[2*k+1].l)change(2*k+1,x,tag);    a[k].ans=min(a[2*k].ans,a[2*k+1].ans);}int ask(int k,int l,int r){    if(a[k].l==l&&a[k].r==r)return a[k].ans;    if(r<=a[2*k].r)return ask(2*k,l,r);    else if(l>=a[2*k+1].l)return ask(2*k+1,l,r);    return min(ask(2*k,l,a[2*k].r),ask(2*k+1,a[2*k+1].l,r));}int main(){    int n,T;    scanf("%d",&n);    for(int i=1;i<=n;i++)e[i].clear();    for(int i=1;i<=n;i++)scanf("%d",&A[i]);    for(int x,i=2;i<=n;i++)    {        scanf("%d",&x);        e[x].push_back(i);    }    dfs(1);    build(1,1,n);    scanf("%d",&T);    while(T--)    {        int op,x,y;        scanf("%d",&op);        if(op==1)        {            scanf("%d%d",&x,&y);            change(1,L[x],y);        }        else        {            scanf("%d",&x);            printf("%d\n",ask(1,L[x],R[x]));        }    }    return 0;}




阅读全文
1 0
原创粉丝点击