和bzoj 3083比就是弱化版了。
样例都有点像?
http://blog.youkuaiyun.com/huanghongxun/article/details/50663457
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100005, M = N * 3, inf = 0x7fffffff;
int read() {
int s = 0, f = 1; char ch = getchar();
for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';
return s * f;
}
int next[M], to[M], head[N], sz[N], son[N], top[N], c[N], f[N], fa[N], dep[N], pos[N], cnt = 0;
int end[N], num[M], lazy[M], rt = 1, n, tot = 0;
void add(int u, int v) {
next[++cnt] = head[u]; head[u] = cnt; to[cnt] = v;
next[++cnt] = head[v]; head[v] = cnt; to[cnt] = u;
}
void dfs1(int x) {
sz[x] = 1; son[x] = 0;
for (int i = head[x]; i; i = next[i])
if (to[i] != fa[x]) {
fa[to[i]] = x; dep[to[i]] = dep[x] + 1;
dfs1(to[i]);
if (sz[to[i]] > sz[son[x]]) son[x] = to[i];
sz[x] += sz[to[i]];
}
}
void dfs2(int x, int t) {
pos[x] = ++tot; top[x] = t;
if (son[x] != 0) dfs2(son[x], t);
for (int i = head[x]; i; i = next[i])
if (to[i] != son[x] && to[i] != fa[x])
dfs2(to[i], to[i]);
end[x] = tot;
}
void pushdown(int t) {
if (lazy[t]) {
num[t * 2 + 1] = lazy[t * 2 + 1] = num[t * 2] = lazy[t * 2] = lazy[t];
lazy[t] = 0;
}
}
void modify(int t, int l, int r, int ql, int qr, int z) {
int mid = l + r >> 1;
if (l == ql && r == qr) { num[t] = lazy[t] = z; return; }
pushdown(t);
if (qr <= mid) modify(t * 2, l, mid, ql, qr, z);
else if (mid < ql) modify(t * 2 + 1, mid + 1, r, ql, qr, z);
else modify(t * 2, l, mid, ql, mid, z), modify(t * 2 + 1, mid + 1, r, mid + 1, qr, z);
num[t] = min(num[t * 2], num[t * 2 + 1]);
}
void modify(int x, int y, int z) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
modify(1, 1, n, pos[fx], pos[x], z);
x = fa[fx], fx = top[x];
}
if (dep[x] > dep[y]) swap(x, y);
modify(1, 1, n, pos[x], pos[y], z);
}
int query(int t, int l, int r, int ql, int qr) {
int mid = l + r >> 1;
if (l == ql && r == qr) return num[t];
pushdown(t);
if (qr <= mid) return query(t * 2, l, mid, ql, qr);
else if (mid < ql) return query(t * 2 + 1, mid + 1, r, ql, qr);
else return min(query(t * 2, l, mid, ql, mid), query(t * 2 + 1, mid + 1, r, mid + 1, qr));
}
int query(int x) {
if (x == rt) return query(1, 1, n, 1, n);
if (pos[rt] < pos[x] || pos[rt] > end[x]) return query(1, 1, n, pos[x], end[x]);
int i, ans = inf;
for (i = head[x]; i; i = next[i])
if (pos[rt] >= pos[to[i]] && pos[rt] <= end[to[i]] && to[i] != fa[x]) {
if (pos[to[i]] > 1)
ans = min(ans, query(1, 1, n, 1, pos[to[i]] - 1));
if (end[to[i]] < n)
ans = min(ans, query(1, 1, n, end[to[i]] + 1, n));
break;
}
return ans;
}
void build(int t, int l, int r) {
int mid = l + r >> 1;
if (l == r) { num[t] = c[l]; return; }
build(t * 2, l, mid); build(t * 2 + 1, mid + 1, r);
num[t] = min(num[t * 2], num[t * 2 + 1]);
}
int main() {
char op[2];
int i, j, m;
n = read(); m = read();
for (i = 1; i <= n; i++) add(i, read()), f[i] = read();
dfs1(rt); dfs2(rt, rt);
for (i = 1; i <= n; i++) c[pos[i]] = f[i];
build(1, 1, n);
while (m--) {
scanf("%s", op);
switch(op[0]) {
case 'E': rt = read(); break;
case 'V': i = read(); j = read(); modify(i, i, j); break;
case 'Q': printf("%d\n", query(read())); break;
}
}
return 0;
}
3306: 树
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 608 Solved: 192
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。