Description
Jiajia 和 Wind 是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia 、Wind 和孩子们决定在家里玩捉迷藏游戏。他们的家很大且构造很奇特,由
N
个屋子和
Input
第一行包含一个整数
N
,表示房间的个数,房间将被编号为
Output
对于每一个操作
Game
,输出一个非负整数到 hide.out
,表示最远的两个关灯房间的距离。若只有一个房间是关着灯的,输出
0
;若所有房间的灯都开着,输出
Sample Input
8
1 2
2 3
3 4
3 5
3 6
6 7
6 8
7
G
C 1
G
C 2
G
C 1
G
Sample Output
4
3
3
4
HINT
对于 100% 的数据, N≤105,M≤5×105 。
题解
动态点分治。
首先处理出所有点到所有分治根节点的距离
dis[ dfn[i][j] ][ j ]
,按照
dfs
序插入到每个分治根节点对应的动态开点线段树中。(这是为了方便查询该节点属于分治根节点的哪一个子树)
然后对于每一个分治根节点 root ,经过该节点的路径长度最大值为:
其中
mx
为最大值所处下标,
l[x]
表示
x
所处子树在
上式的意思是如果 rt 开着并且只有一个子树有关的灯,那么就没有路径经过 rt 。其他情况就是以 rt 为分治根的子树距离的最大值 + 不在该最大值节点所在子树的节点距离的最大值。
然后修改
x
的时候就可以遍历所有的包含节点
查询的时候可以再开一颗线段树,存储每个分治根节点的答案,单点修改,查询 1∼n 的最大值(好像也可以用手写堆)
复杂度 O((n+m)log22n) 。
My Code
代码很长(共 8KB),写的时候要注意细节和边界情况。当然我的代码有一些地方可以简化。
不要犯一些制杖性错误。
/**************************************************************
Problem: 1095
User: infinityedge
Language: C++
Result: Accepted
Time:32113 ms
Memory:214388 kb
****************************************************************/
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <complex>
#define inf 0x3f3f3f3f
#define eps 1e-10
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
struct edge {
int to, w, nxt;
} e[200005];
int h[100005], cnt;
void addedge(int x, int y) {
cnt++; e[cnt].to = y; e[cnt].nxt = h[x]; h[x] = cnt;
cnt++; e[cnt].to = x; e[cnt].nxt = h[y]; h[y] = cnt;
}
int n, m;
int vis[100005], siz[100005], dep[100005], tp[100005], ans[100005], Ans[100005], dis[100005][17], dfn[100005][17], root[100005];
int b[100005], Dfn[100005], end[100005], Ct, cnt_open;
vector<int> vec[100005];
int N, rt, ct, ansroot;
struct node{
int l, r, lc, rc;
P dat;
}d[100005 * 20 * 2 * 2];
int seg_sz;
void pushup(int k){
d[k].dat = make_pair(-inf, 0);
if(d[k].lc) d[k].dat = d[d[k].lc].dat;
if(d[k].rc) {
if(d[d[k].rc].dat.first > d[k].dat.first) d[k].dat = d[d[k].rc].dat;
}
}
void ins(int &k, int l, int r, int pos, int x){
if(k == 0) k = ++seg_sz;
d[k].l = l, d[k].r = r;
if(l == r) {
d[k].dat = make_pair(x, pos);
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) ins(d[k].lc, l, mid, pos, x);
else ins(d[k].rc, mid + 1, r, pos, x);
pushup(k);
}
void modify(int k, int pos, int x){
if(k == 0) return;
if(d[k].l == d[k].r){
d[k].dat = make_pair(x, pos);
return;
}
int mid = (d[k].l + d[k].r) >> 1;
if(pos <= mid) modify(d[k].lc, pos, x);
else modify(d[k].rc, pos, x);
pushup(k);
}
P query(int k, int l, int r){
if(k == 0) return make_pair(-inf, 0);
if(l <= d[k].l && d[k].r <= r){
return d[k].dat;
}
int mid = (d[k].l + d[k].r) >> 1;
P sum = make_pair(-inf, 0);
if(l <= mid) {
P tmp = query(d[k].lc, l, r);
if(tmp.first > sum.first) sum = tmp;
}
if(r > mid) {
P tmp = query(d[k].rc, l, r);
if(tmp.first > sum.first) sum = tmp;
}
return sum;
}
void dfs_root(int x, int f){
siz[x] = 1; int mx = 0;
for(int i = h[x]; i; i = e[i].nxt){
if(e[i].to == f || vis[e[i].to]) continue;
dfs_root(e[i].to, x);
mx = max(mx, siz[e[i].to]);
siz[x] += siz[e[i].to];
}
if(max(mx, N - siz[x] - 1) <= N / 2) rt = x;
}
void dfs_size(int x, int f){
siz[x] = 1;
for(int i = h[x]; i; i = e[i].nxt){
if(e[i].to == f || vis[e[i].to]) continue;
dfs_size(e[i].to, x);
siz[x] += siz[e[i].to];
}
}
void dfs_tag(int x, int f, int de){
dep[x] = de;
for(int i = h[x]; i; i = e[i].nxt){
if(e[i].to == f || vis[e[i].to]) continue;
tp[e[i].to] = rt;
dfs_tag(e[i].to, x, de);
}
}
void dfs_ans(int x, int f){
dis[x][dep[x]] = dis[f][dep[x]] + 1;
dfn[x][dep[x]] = ++ct;
ins(root[rt], 1, N, dfn[x][dep[x]], dis[x][dep[x]]);
for(int i = h[x]; i; i = e[i].nxt){
if(e[i].to == f || vis[e[i].to]) continue;
dfs_ans(e[i].to, x);
}
}
void solve(int x, int cur){
dfs_root(x, 0);
Dfn[rt] = end[rt] = ++Ct;
dfs_size(rt, 0);
dfs_tag(rt, 0, cur);
ins(root[rt], 1, N, 1, 0);
ct = 1;
for(int i = h[rt]; i; i = e[i].nxt){
if(vis[e[i].to]) continue;
vec[rt].push_back(ct);
dfs_ans(e[i].to, rt);
}
vec[rt].push_back(ct + 1);
P r1 = query(root[rt], 1, N);
int r = lower_bound(vec[rt].begin(), vec[rt].end(), r1.second) - vec[rt].begin();
int l = r - 1;
l = vec[rt][l], r = vec[rt][r];
P r2 = make_pair(-inf, 0), r3 = make_pair(-inf, 0);
if(l >= 1) r2 = query(root[rt], 1, l);
if(r < N) r3 = query(root[rt], r + 1, N);
if(r3.first > r2.first) r2 = r3;
Ans[rt] = ans[rt] = r1.first + r2.first;
vis[rt] = 1;
int trt = rt;
for(int i = h[trt]; i; i = e[i].nxt){
if(vis[e[i].to]) continue;
if(siz[e[i].to] == 1) continue;
N = siz[e[i].to];
solve(e[i].to, cur + 1);
Ans[trt] = max(Ans[trt], Ans[e[i].to]);
end[trt] = Ct;
}
ins(ansroot, 1, n, Dfn[trt], Ans[trt]);
}
void solvemodify(int x){
if(b[x] == 0){
b[x] = 1; cnt_open --;
int mxdep = dep[x], rtp = tp[x];
if(Dfn[x]) {
mxdep--;
// printf("%d ", Ans[x]);
modify(root[x], 1, -inf);
N = d[root[x]].r;
P r1 = query(root[x], 1, N);
int r = lower_bound(vec[x].begin(), vec[x].end(), r1.second) - vec[x].begin();
int l = r - 1;
l = vec[x][l], r = vec[x][r];
P r2 = make_pair(-inf, 0), r3 = make_pair(-inf, 0);
if(l >= 1) r2 = query(root[x], 1, l);
if(r < N) r3 = query(root[x], r + 1, N);
if(r3.first > r2.first) r2 = r3;
if(b[x] == 1 && r2.first == 0) r1.first = 0;
Ans[x] = ans[x] = r1.first + r2.first;
modify(ansroot, Dfn[x], Ans[x]);
// printf("%d\n", Ans[x]);
}
for(int i = mxdep; i >= 0; i --){
// printf("%d ", Ans[rtp]);
modify(root[rtp], dfn[x][i], 0);
N = d[root[rtp]].r;
P r1 = query(root[rtp], 1, N);
int r = lower_bound(vec[rtp].begin(), vec[rtp].end(), r1.second) - vec[rtp].begin();
int l = r - 1;
l = vec[rtp][l], r = vec[rtp][r];
P r2 = make_pair(-inf, 0), r3 = make_pair(-inf, 0);
if(l >= 1) r2 = query(root[rtp], 1, l);
if(r < N) r3 = query(root[rtp], r + 1, N);
if(r3.first > r2.first) r2 = r3;
if(b[rtp] == 1 && r2.first == 0) r1.first = 0;
ans[rtp] = r1.first + r2.first;
// printf("%d %d %d %d ", r1.first, r1.second, r2.first, r2.second);
modify(ansroot, Dfn[rtp], ans[rtp]);
Ans[rtp] = query(ansroot, Dfn[rtp], end[rtp]).first;
// printf("%d\n", Ans[rtp]);
rtp = tp[rtp];
}
}else{
b[x] = 0; cnt_open ++;
int mxdep = dep[x], rtp = tp[x];
if(Dfn[x]) {
mxdep--;
// printf("%d ", Ans[x]);
modify(root[x], 1, 0);
N = d[root[x]].r;
P r1 = query(root[x], 1, N);
int r = lower_bound(vec[x].begin(), vec[x].end(), r1.second) - vec[x].begin();
int l = r - 1;
l = vec[x][l], r = vec[x][r];
P r2 = make_pair(-inf, 0), r3 = make_pair(-inf, 0);
if(l >= 1) r2 = query(root[x], 1, l);
if(r < N) r3 = query(root[x], r + 1, N);
if(r3.first > r2.first) r2 = r3;
if(b[x] == 1 && r2.first == 0) r1.first = 0;
Ans[x] = ans[x] = r1.first + r2.first;
modify(ansroot, Dfn[x], Ans[x]);
// printf("%d\n", Ans[x]);
}
for(int i = mxdep; i >= 0; i --){
// printf("%d ", Ans[rtp]);
modify(root[rtp], dfn[x][i], dis[x][i]);
N = d[root[rtp]].r;
P r1 = query(root[rtp], 1, N);
int r = lower_bound(vec[rtp].begin(), vec[rtp].end(), r1.second) - vec[rtp].begin();
int l = r - 1;
l = vec[rtp][l], r = vec[rtp][r];
P r2 = make_pair(-inf, 0), r3 = make_pair(-inf, 0);
if(l >= 1) r2 = query(root[rtp], 1, l);
if(r < N) r3 = query(root[rtp], r + 1, N);
if(r3.first > r2.first) r2 = r3;
if(b[rtp] == 1 && r2.first == 0) r1.first = 0;
ans[rtp] = r1.first + r2.first;
// printf("%d %d %d %d ", r1.first, r1.second, r2.first, r2.second);
modify(ansroot, Dfn[rtp], ans[rtp]);
Ans[rtp] = query(ansroot, Dfn[rtp], end[rtp]).first;
// printf("%d\n", Ans[rtp]);
rtp = tp[rtp];
}
}
}
int main() {
// freopen("test.in", "r", stdin);
// freopen("test.out", "w", stdout);
scanf("%d", &n);
for (int i = 1; i < n; i ++) {
int x, y;
scanf("%d%d", &x, &y);
addedge(x, y);
}
N = n; cnt_open = n;
solve(1, 0);
scanf("%d", &m);
char ch[5];
for(int i = 1; i <= m; i ++){
scanf("%s", ch);
if(ch[0] == 'G'){
if(cnt_open == 1){
printf("0\n");
continue;
}
if(cnt_open == 0){
printf("-1\n");
continue;
}
printf("%d\n", query(ansroot, 1, n).first);
}else{
int x;
scanf("%d", &x);
solvemodify(x);
}
}
return 0;
}