bzoj1095

有什么不懂看这个老铁的,他才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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值