hihocoder#1576 : 子树中的最小权值(dfs序+线段树)
2017-09-20 12:54
351 查看
时间限制: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
对于每次询问,输出一个整数表示答案。
样例输入
样例输出
思路: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;
}
单点时限: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
输出
对于每次询问,输出一个整数表示答案。样例输入
12 3 5 -1 -2 9 6 2 8 -10 11 8 10 1 1 1 2 4 2 6 7 7 8 8 10 2 3 2 1 2 6 1 11 -5 1 5 -12 2 6 2 4 2 2 2 1 2 7
样例输出
-1 -10 6 -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;
}
相关文章推荐
- hihoCoder1576 子树中的最小权值 dfs序+线段树
- 【HIHOCODER 1576】 子树中的最小权值(线段树维护DFS序)
- HihoCoder1576 子树中的最小权值( dfs序 +线段树 || 树剖)
- hiho1576 子树中的最小权值【dfs序】
- poj 3662 二分+最短路,求第k大最小权值
- uva 11090 Going in Cycle!! 平均权值最小的回路
- (kruscal12.2.1)POJ 1258 Agri-Net(使用kruscal来计算最小边权值)
- 求 二叉树中权值最大和最小的叶节点之间的距离
- 洛谷 1576 最小花费
- hdu 1853 Cyclic Tour(KM 最小权值匹配)
- 51Nod 1110 距离之和最小 V3(中位数+权值转化为个数)
- POJ-2195 Going Home 最小权值匹配
- 【证明】最大闭合权值 最小路径覆盖
- poj 2455 Secret Milking Machine 【二分 + 最大流】 【1到N不重复路径不少于T条时,求被选中路径上的最大边权值 的最小值】
- bellman_ford寻找平均权值最小的回路
- find the most comfortable road(并差集,找差值最小的权值)
- poj 2516 Minimum Cost KM算法 最小权值匹配
- uva 11090 Going in Cycle!! (求平均权值最小的环路)
- Prim 算法实现最小生成树 打印出对应的最小生成树和最小生成树的总权值
- hdu 1598 并查集+枚举最小权值