有什么不懂看这个老铁的,他才14岁orz
http://blog.csdn.net/Hanks_o/article/details/77605924
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
struct edgee
{
int from, to, cost;
edgee(int f, int t, int c) :from(f), cost(c), to(t)
{}
edgee(){}
};
int edgetot;
edgee edge[200005];
int first[100008], nextt[200005];
int id[100008], st[300000][30];
int bit[30], logg[300000];
int fa[100020], size[100020], root, maxroot = 1000000000, isroot[100020],ison[100020];
int n, m,closenum;
struct que
{
priority_queue<int>in, out;//为什么要两个?因为有些时候我们并不会删掉队列中的最大值所以把那些要删除的放在out中等那些在in的数是队头时再删除
void push(int n)
{
if (n&&n!=-1)
in.push(n);
}
void pop(int n)
{
if (n&&n!=-1)
out.push(n);
}
int front()
{
while (!out.empty()&&in.top() == out.top())
in.pop(), out.pop();//现在才是真正的删除
return in.top();
}
int sfront()//找第二大
{
int tt = front();
pop(tt);
int qq = front();
push(tt);
return qq;
}
int size()
{
return in.size() - out.size() - 1;
}
que()
{
in.push(0);//初始话让0在里面否则会re
maxx = -1, maxxfa = -1;
}
int maxx, maxxfa;
};
que f[100040], s[100040], all;//first,second,all
void addedge(int from, int to, int cost)
{
edge[edgetot] = edgee(from, to, 1);
nextt[edgetot] = first[from];
first[from] = edgetot++;
edge[edgetot] = edgee(to, from, 1);
nextt[edgetot] = first[to];
first[to] = edgetot++;
}
void dfs(int num, int fa, int d, int &nu)
{
if (id[num] == -1)id[num] = nu;
st[nu][0] = d; size[num] = 1; int temp = -1;
for (int i = first[num]; i != -1; i = nextt[i])
{
int to = edge[i].to;
if (to != fa)
{
int k = nu + 1;
dfs(to, num, d + 1, k);
size[num] += size[to];
temp = max(temp, size[to]);
nu = k + 1; st[nu][0] = st[id[num]][0];
}
}
if (maxroot > max(temp, n - size[num]))
{
root = num; maxroot = max(temp, n - size[num]);
}
}
void getst(int n)
{
logg[0] = -1; bit[0] = 1;
int kk = 0;
for (int i = 0; i <= n; i++)id[i] = -1;
maxroot = 1000000000;
dfs(1, 1, 0, kk);
for (int i = 1; i < 30; i++)bit[i] = bit[i - 1] * 2;
for (int i = 1; i <= kk; i++)logg[i] = logg[i / 2] + 1;
for (int i = 1; i <= logg[kk]; i++)
{
for (int j = 0; j <= kk - bit[i]; j++)
{
st[j][i] = min(st[j][i - 1], st[j + bit[i - 1]][i - 1]);
}
}
}
int getd(int num1, int num2)
{
int id1 = id[num1]; int id2 = id[num2];
if (id1>id2)swap(id1, id2);
int kk = logg[id2 - id1 + 1];
return st[id1][0] + st[id2][0] - 2 * min(st[id1][kk], st[id2 - bit[kk] + 1][kk]);
}
void getsize(int num, int fa, int all)
{
size[num] = 1; int temp = -1;
for (int i = first[num]; i != -1; i = nextt[i])
{
int to = edge[i].to;
if (to == fa || isroot[to])continue;
getsize(to, num, all);
temp = max(temp, size[to]);
size[num] += size[to];
}
if (maxroot > max(temp, all - size[num]))
{
root = num; maxroot = max(temp, all - size[num]);
}
}
void work(int num, int faa, int all)
{
fa[num] = faa; int elsee = 1; int temp = -1;
for (int i = first[num]; i != -1; i = nextt[i])
{
int to = edge[i].to;
if (isroot[to] || st[id[to]][0] < st[id[num]][0])//这要防止是root
{
if (st[id[to]][0] < st[id[num]][0]&&!isroot[to])
temp = to;
continue;
}
maxroot = 1000000000;
getsize(to, num, size[to]);
isroot[root] = 1; elsee += size[to];
work(root, num, size[to]);
}
elsee = all - elsee;
if (temp != -1)
{
maxroot = 1000000000;
getsize(temp, num, elsee);
isroot[root] = 1;
work(root, num, elsee);
}
}
int check(int now)
{
int tempp = s[now].front(); int stempp = s[now].sfront();
if (s[now].size() >= 2 || (s[now].size() == 1 && !ison[now]))
return tempp + stempp;
else
return -1000000000;
}
void init1(int num,int now)
{
for (int i =now; fa[i]; i = fa[i])
{
int d = getd(num, fa[i]); f[i].push(d); f[i].maxxfa = max(f[i].maxxfa, d);
}
}
void init2(int num){ if (fa[num])s[fa[num]].push(f[num].front()); }
void init3(int num)
{
int t = check(num);
if (t != -1000000000)all.push(t), s[num].maxx = t;
}
void turnoff(int num,int now)
{
int t = check(now);
if (t != -1000000000 && t > s[now].maxx)
all.pop(s[now].maxx), all.push(t), s[now].maxx = t;
if (fa[now] == 0)return;
int d = getd(num, fa[now]);
f[now].push(d);
d = f[now].front();
if (d > f[now].maxxfa)s[fa[now]].pop(f[now].maxxfa), s[fa[now]].push(d), f[now].maxxfa = d;
turnoff(num, fa[now]);
return;
}
void turnon(int num, int now)
{
int t = check(now);
if (t == -1000000000 || t < s[now].maxx)
{
if (s[now].maxx != -1)
{
all.pop(s[now].maxx);
if (t != -1000000000) all.push(t);
s[now].maxx = (t == -1000000000 ? -1 : t);
}
}
if (fa[now] == 0)return;
int d = getd(num, fa[now]);
f[now].pop(d); d = f[now].front();
if (d < f[now].maxxfa)s[fa[now]].pop(f[now].maxxfa), s[fa[now]].push(d), f[now].maxxfa = (d==0?-1:d);
turnon(num, fa[now]);
return;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i <= n; i++)first[i] = -1;
for (int i = 1; i <n; i++)
{
int a, b;
scanf("%d%d", &a, &b);
addedge(a, b, 1);
//addedge(i, i + 1,1);
}
getst(n);
isroot[root] = 1;
work(root, 0, n);
for (int i = 1; i <= n; i++)
init1(i,i);
for (int i = 1; i <= n; i++)init2(i);
for (int i = 1; i <= n; i++)init3(i);
closenum = n;
scanf("%d", &m);
while (m--)
{
char s[10];
scanf("%s", s);
if (s[0] == 'G')
{
if (closenum < 2)
{
if (closenum == 1)
printf("0\n");
else
printf("-1\n");
}
else
{
printf("%d\n", all.front());
}
}
else
{
int a;
scanf("%d", &a);
if (ison[a])
{
closenum++;
ison[a] = 0;
turnoff(a, a);
}
else
{
closenum--;
ison[a] = 1;
turnon(a, a);
}
}
}
return 0;
}