BZOJ 1146: [CTSC2008]网络管理Network

Description

M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个

部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。

每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部

门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。 高速光

缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行

数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的

交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况

。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通

信路径上延迟第k大的路由器的延迟时间。【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息

,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们

可能是: 1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。 2. 查

询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。

Input

第一行为两个整数N和Q,分别表示路由器总数和询问的总数。第二行有N个整数,第i个数表示编号为i的路由

器初始的数据延迟时间Ti。紧接着N-1行,每行包含两个整数x和y。表示有一条光缆连接路由器x和路由器y。紧接

着是Q行,每行三个整数k、a、b。如果k=0,则表示路由器a的状态发生了变化,它的数据交换延迟时间由Ta变为b

。如果k>0,则表示询问a到b的路径上所经过的所有路由器(包括a和b)中延迟第k大的路由器的延迟时间。注意N

,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。对于所有询问满足0<=K<=N

Output

对于每一个第二种询问(k>0),输出一行。包含一个整数为相应的延迟时间。如果路径上的路由器不足k个,

则输出信息“invalid request!”(全部小写不包含引号,两个单词之间有一个空格)。

Sample Input

5 5

5 1 2 3 4

3 1

2 1

4 3

5 3

2 4 5

0 1 2

2 2 3

2 1 4

3 3 5

Sample Output

3

2

2

invalid request!

Solution

树套树+二分。

先树链剖分,然后建立线段树,每个节点存l…r的一颗平衡树。每次询问二分答案,利用树链剖分在线段树上找区间,然后在平衡树上找大于等于这个数的个数。

复杂度O(Nlog^4N)。

一开始TLE了,那过测试数据来反复优化常数,本地22秒硬是优化到了16秒…交一发,TLE…然后恍惚中突然看到我树链剖分用的size是平衡树的size….

然后赶紧交了一发,A了。。。

以后这种丧心病狂的A套B套C的东西应该强行写个namespace QAQ。。。

(貌似这道题可以用主席树,复杂度优化为O(Nlog^3N)。)

Code

发一波常数优化过后的…

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 80005;
inline int getint() {
	int r = 0, k = 1; char c = getchar();
	for (; '0' > c || c > '9'; c = getchar()) if (c == '-') k = -1;
	for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;
	return r * k;
}
char dst[1024]; int ptr;
inline void putint(int x) {
	for (; x; x /= 10)
		dst[++ptr] = x % 10;
	while (ptr) putchar(dst[ptr--]+'0');
	putchar('\n');
}
struct Edge {int to, next;} edge[N<<1];
int n, q, x, y, k, dep[N], top[N], A[N], B[N], T[N], cnte = 1, fat[N], hah[N], son[N], dfn[N], clo, tot, root[N<<2], h[N], lc[N*30], rc[N*30], siz[N*30], tim[N*30], val[N*30], fa[N*30];
inline void ins(int x, int y) {
	edge[++cnte].to = y;
	edge[cnte].next = h[x];
	h[x] = cnte;
}
inline void pu(int x) { siz[x] = siz[lc[x]] + siz[rc[x]] + tim[x]; }
inline void rotate(int x) {
	int y = fa[x], z = fa[y];
	if (z) {
	   if (rc[z]==y) rc[z] = x;
	   else lc[z] = x;
	}
	if (rc[y] == x) {
		fa[x] = z; fa[y] = x; fa[lc[x]] = y; fa[0] = 0;
		rc[y] = lc[x]; lc[x] = y;
		pu(y); pu(x);
	} else {
		fa[x] = z; fa[y] = x; fa[rc[x]] = y; fa[1] = 0;
		lc[y] = rc[x]; rc[x] = y;
		pu(y); pu(x);
	}
}
inline void splay(int x) {
	while (fa[x]) {
		int y = fa[x], z = fa[y];
		if (z) {
			if (lc[y] == x ^ lc[z] == y) rotate(x);
			else rotate(y);
		}
		rotate(x);
	}
}
void Insert(int &rt, int &x, int key, int father) {
	if (!x) {
		x = ++tot;
		val[tot] = key;
		fa[tot] = father;
		tim[tot] = siz[tot] = 1;
		splay(tot);
		rt = tot;
		return;
	} else {
		++siz[x];
		if (val[x] == key) {
			++tim[x];
			key = x;
			splay(key);
			rt = key;
			return;
		}
		if (val[x] < key) Insert(rt, rc[x], key, x);
		else Insert(rt, lc[x], key, x);
	}
}
inline void Delete(int &rt, int key) {
	for (int x = rt; x; ) {
		if (val[x] == key) {
			splay(x);
			rt = x;
			--siz[x]; --tim[x];
			return;
		}
		if (val[x] < key) x = rc[x];
		else x = lc[x];
	}
}
inline int CountGreater(int &rt, int key) {
	int x = rt, y = 0;
	while (x) {
		if (val[x] < key) { y = x; x = rc[x]; }
		else x = lc[x];
	}
	if (!y) return siz[rt];
	else {
		splay(y);
		rt = y;
		return siz[rc[y]];
	}
}
int sgtCountGreater(int now, int l, int r, int ll, int rr, int val) {
	if (ll <= l && r <= rr) return CountGreater(root[now], val);
	int mid = (l + r) >> 1, ret = 0;
	if (ll <= mid) ret = sgtCountGreater(now << 1, l, mid, ll, rr, val);
	if (rr > mid) ret += sgtCountGreater(now << 1 | 1, mid+1, r, ll, rr, val);
	return ret;
}
int L[N], R[N], Orz;
inline int MagHSK(int val) {
	int ret = 0;
	for (int i = 1; i <= Orz; ++i)
		ret += sgtCountGreater(1, 1, n, L[i], R[i], val);
	return ret;
}
inline int lca(int u, int v) {
	Orz = 0;
	while (top[u] != top[v]) {
		if (dep[top[u]] < dep[top[v]]) swap(u, v);
		L[++Orz] = dfn[top[u]];
		R[Orz] = dfn[u];
		u = fat[top[u]];
	}
	if (dep[u] < dep[v]) swap(u, v);
	L[++Orz] = dfn[v];
	R[Orz] = dfn[u];
	return v;
}
inline void Query(int x, int y, int k) {
	int acl = lca(x, y);
	if (dep[x] + dep[y] - dep[acl] - dep[acl] + 1 < k) {
		puts("invalid request!");
		return;
	}
	int l = 1, r = 100000000, mid;
	while (l < r) {
		mid = (l + r + 1) >> 1;
		int tmp = MagHSK(mid);
		if (tmp < k) r = mid - 1;
		else l = mid;
	}
	putint(l);
}
void sgtChange(int now, int l, int r, int pos, int delval, int insval) {
	if (l == r) {
		val[root[now]] = insval;
		return;
	}
	Delete(root[now], delval);
	Insert(root[now], root[now], insval, 0);
	int mid = (l + r) >> 1;
	if (pos <= mid) sgtChange(now << 1, l, mid, pos, delval, insval);
	else sgtChange(now << 1 | 1, mid+1, r, pos, delval, insval);
}
int dfs1(int now, int father, int deep) {
	dep[now] = deep; hah[now] = 1; fat[now] = father;
	for (int i = h[now]; i; i = edge[i].next) {
		if (edge[i].to == father) continue;
		hah[now] += dfs1(edge[i].to, now, deep+1);
		if (hah[edge[i].to] > hah[son[now]])
			son[now] = edge[i].to;
	}
	return hah[now];
}
void dfs2(int now, int father, int tp) {
	top[now] = tp; dfn[now] = ++clo; A[clo] = T[now];
	if (son[now]) {
		dfs2(son[now], now, tp);
		for (int i = h[now]; i; i = edge[i].next) {
			if (edge[i].to == father || edge[i].to == son[now]) continue;
			dfs2(edge[i].to, now, edge[i].to);
		}
	}
}
void build(int now, int l, int r) {
	for (int i = l; i <= r; ++i) Insert(root[now], root[now], A[i], 0);
	if (l == r) return;
	int mid = (l + r) >> 1;
	build(now << 1, l, mid);
	build(now << 1 | 1, mid + 1, r);
}
int main() {
	n = getint(); q = getint();
	for (int i = 1; i <= n; ++i)
		T[i] = getint();
	for (int i = 1; i < n; ++i) {
		x = getint(); y = getint();
		ins(x, y); ins(y, x);
	}
	dfs1(1, 0, 1);
	dfs2(1, 0, 1);
	build(1, 1, n);
	for (int i = 1; i <= q; ++i) {
		k = getint(); x = getint(); y = getint();
		if (k) Query(x, y, k);
		else {
			sgtChange(1, 1, n, dfn[x], T[x], y);
			T[x] = y;
		}
	}
}