3306: 树
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 654 Solved: 208
Description
给定一棵大小为 n 的有根点权树,支持以下操作:
• 换根
• 修改点权
• 查询子树最小值
Input
第一行两个整数 n, Q ,分别表示树的大小和操作数。
接下来n行,每行两个整数f,v,第i+1行的两个数表示点i的父亲和点i的权。保证f < i。如 果f = 0,那么i为根。输入数据保证只有i = 1时,f = 0。
接下来 m 行,为以下格式中的一种:
• V x y表示把点x的权改为y
• E x 表示把有根树的根改为点 x
• Q x 表示查询点 x 的子树最小值
Output
对于每个 Q ,输出子树最小值。
Sample Input
3 7
0 1
1 2
1 3
Q 1
V 1 6
Q 1
V 2 5
Q 1
V 3 4
Q 1
Sample Output
1
2
3
4
HINT
对于 100% 的数据:n, Q ≤ 10^5。
链剖裸题。。
对于换根操作同遥远的国度一样。。
附上本蒟蒻的代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<climits>
using namespace std;
#define MAXN 100001
int n,m,cnt,root,sz,a[MAXN],h[MAXN],father[MAXN][17],pos[MAXN],belong[MAXN],deep[MAXN],size[MAXN],mx[MAXN],delta[MAXN<<2];
bool vis[MAXN];
struct data
{
int to,next;
}edge[MAXN<<1];
struct kx
{
int value;
}node[MAXN<<2];
int read()
{
int w=0,c=1; char ch=getchar();
while (ch<'0' || ch>'9')
{
if (ch=='-') c=-1;
ch=getchar();
}
while (ch>='0' && ch<='9')
w=w*10+ch-'0',ch=getchar();
return w*c;
}
void add(int u,int v)
{
cnt++,edge[cnt].next=h[u],h[u]=cnt,edge[cnt].to=v;
}
void dfs1(int x)
{
int i;
size[x]=1,vis[x]=true;
for (i=1;i<=16;i++)
{
if (deep[x]<(1<<i))