[qtree4]坑爹啊!!!!(Update)

膜拜邓神!!!比我少写半个星期以上还比我先A!!ORZ!!!!!


膜拜啊。。。我太弱了。。。


原来的坑爹错误:down写错了!!!!!我不管是和左儿子还是右儿子都是直接num<<1 啊!!!

调试了一天啊!!!死活拍不出来啊!!!!我了个去啊!!!


又写了一次数链剖分。spoj第7....好开心....真的很快...是边分治的若干倍(本机2倍,spoj上4倍)

但是边分治怎么也过不了....求破.....


数链破分:(做法见QZC论文...虽然我没看懂。我的做法是对每个点的所有非重儿子建两个堆...然后乱搞...)

//Qtree4_heavy-light-decomposition
#include<cstdio> 
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<climits>
#include<iostream>
#define max(a, b) ({int _ = (a), __ = (b); _ > __ ? _ : __;})
#define swap(___, a, b) ({___ _ = (a); (a) = (b); (b) = _;})
#define maxn 204800
#define fort(_, __, ___) for (int _ = (__); _ <= (___); ++_)
#define fot(_, __, ___) for (int _ = (__); _ < (___); ++_)
#define ms(a, b) memset(a, b, sizeof a)
#define openfile() freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
#define adde(a, b, c)																										\
	({*(++eptr) = (edge){b, c, h[a]}, h[a] = eptr;												\
		*(++eptr) = (edge){a, c, h[b]}, h[b] = eptr;})
#define abs(_) ({int __ = _; __ < 0 ? -__ : __;})
#define upit(_, __) if (_ -> ans < __ -> ans) _ -> ans = __ -> ans;

struct node {int val, pos; node *f, *c[2];}
	heap[maxn << 1], *nptr, *to_heap[maxn], *to_ah[maxn], *null, *hth[maxn], *ansh[maxn];
struct edge {int t, v; edge *nt;}
	eg[maxn << 1], *eptr, *h[maxn];
struct tree {int x, y, ans, from; tree *l, *r, *f;}
	seg[maxn << 1], *seg_rot[maxn], *to_seg[maxn], *sptr;

const int inf = 100000000; char rd, order; int fu;
inline void read(int &a)
{
  a = 0; rd = getchar(); while (('0' > rd || rd > '9') && rd != '-') rd = getchar();
  rd == '-' ? fu = -1, rd = getchar() : fu = 1;
  while ('0' <= rd && rd <= '9') a *= 10, a += rd - '0', rd = getchar();
  a *= fu;
}

typedef int arr[maxn];
arr s, q, ef, aux, l, r, x, y, f, mid, pos, length, weight;
int n, ques, a, u, v, white_num, ans;
bool color[maxn];

inline node *merge(node *a, node *b)
{
	if (a == null) return b;
	if (b == null) return a;
	if (a -> val < b -> val) swap(node *, a, b); a -> f = null;
	return b = merge(a -> c[1], b), a -> c[1] = a -> c[0], (a -> c[1] = b) -> f = a;
}

inline node *build_h(int k, node **tt)
{
	node *root = null;
	for(edge *e = h[k]; e; e = e -> nt)
		if (e -> t != aux[k])
			root = merge(root, tt[e -> t]);
	return root;
}

inline tree *build(int s, int t)
{
	if (s == t)
		{
			tree *p = ++sptr; node *th = to_heap[u] = build_h(u, hth);
			int tmp = max(0, th -> val), tmp2 = max(0, max(th -> c[0] -> val, th -> c[1] -> val));
			*p = (tree){-pos[u] + tmp, pos[u] + tmp, tmp + tmp2, u, 0, 0, 0};
			if (p -> ans < (to_ah[u] = build_h(u, ansh)) -> val) p -> ans = to_ah[u] -> val;
			to_seg[u] = p; u = aux[u]; return p;
		}
	int md = (s + t) >> 1; tree *l = build(s, md), *p = ++sptr, *r = build(md + 1, t);
	*p = (tree){max(l -> x, r -> x), max(l -> y, r -> y), l -> x + r -> y, 0, l, r, 0};
	if (l -> y > r -> y) p -> from = l -> from; else p -> from = r -> from;
	p -> ans = max(max(l -> ans, r -> ans), p -> ans);
	l -> f = r -> f = p; upit(p, l); upit(p, r);
	// X : -sum[x] + maxlen[x]; Y : sum[y] + maxlen[y];
	return p;
}

inline void prepare()
{
	read(n); eptr = eg; int a, b, c; tree *tr;
	fot(i, 1, n) read(a), read(b), read(c), adde(a, b, c);
	int head = 0, tail = 1, maxsize; q[1] = 1;
	white_num = n; nptr = heap; sptr = seg; read(ques);
	null = heap; *null = (node){-inf, 0, null, {null, null}};
	while (head != tail)
		{
			u = q[++head];
			if (h[u] -> t == ef[u]) h[u] = h[u] -> nt;
			for(edge *e = h[u]; e; e = e -> nt)
				{
					ef[q[++tail] = e -> t] = u;
					if (e -> nt) if (e -> nt -> t == ef[u]) e -> nt = e -> nt -> nt;
				}
		}
	for(int i = n; i; --i)
		{
			s[u = q[i]] = 1; maxsize = 0;
			for(edge *e = h[u]; e; e = e -> nt)
				{
					s[u] += s[v = e -> t];
					if (s[v] > maxsize) aux[u] = v, maxsize = s[v];
					weight[v] = pos[v] = e -> v;
				}
		}
	fort(i, 1, n)
		if (!f[u = q[i]])
			{
				length[u] = 1; pos[u] = 0; f[u] = u;
				for(int j = aux[u]; j; j = aux[j])
					f[j] = u, ++length[u], pos[aux[j]] += pos[j];
			}
	for(int i = n; i; --i)
		if (f[u = q[i]] == q[i])
			{
				tr = seg_rot[q[i]] = build(1, length[u]); u = q[i];
				*(hth[u] = ++nptr)  = (node){tr -> y + weight[u], tr -> from, null, {null, null}};
				*(ansh[u] = ++nptr) = (node){tr -> ans, u, null, {null, null}};
			}
	ans = seg_rot[1] -> ans;
}

inline void up_seg(int u)
{
	tree *p = to_seg[u];node *th = to_heap[u];
	int tmp = th -> val, tmp2 = max(th -> c[0] -> val, th -> c[1] -> val);
	if (!color[u]) {if (tmp < 0) tmp = tmp2 = 0; else if (tmp2 < 0) tmp2 = 0;}
	*p = (tree){-pos[u] + tmp, pos[u] + tmp, tmp + tmp2, u, p -> l, p -> r, p -> f};
	if (p -> ans < to_ah[u] -> val) p -> ans = to_ah[u] -> val; p = p -> f;
	while (p)
		{
			p -> x = max(p -> l -> x, p -> r -> x);
			p -> y = max(p -> l -> y, p -> r -> y);
			p -> ans = p -> l -> x + p -> r -> y;
			upit(p, p -> l); upit(p, p -> r);
			if (p -> y == p -> l -> y) p -> from = p -> l -> from;
			else p -> from = p -> r -> from;
			p = p -> f;
		}
}

inline void getit(int k, node **t, node **t2, int ct, node *&a)
{
	node *d, *h, *q;
	d = t[k]; h = merge(d -> c[0], d -> c[1]);
	d -> c[0] = d -> c[1] = null; d -> val = ct;
	if (d -> f == null) h = merge(d, h);
	else
		{
			q = d -> f; q -> c[q -> c[1] == d] = null;
			d -> f = null; h = merge(d, merge(t2[ef[k]], h)); 
		}
	a = h;
}

inline void fresh(int k)
{
	for(;;)
		{
			up_seg(k); k = f[k]; if (k == 1) break;
			getit(k, hth, to_heap, seg_rot[k] -> y + weight[k], to_heap[ef[k]]);
			getit(k, ansh, to_ah, seg_rot[k] -> ans, to_ah[ef[k]]); k = ef[k];
		}
}

inline void update(int k)
{
	if (color[k])
		++white_num, color[k] = 0;
	else
		--white_num, color[k] = 1;
	fresh(k);	ans = seg_rot[1] -> ans;
}

int main()
{
	openfile();
	prepare();
	while(ques--)
		{
			order = getchar(); while (order > 'C' || order < 'A') order = getchar();
			if (order == 'A')
				if (!white_num)
					puts("They have disappeared.");
				else
					if (white_num == 1)
						puts("0");
					else
						printf("%d\n", ans > 0 ? ans : 0);
			else
				read(a), update(a);
		}
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值