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大的路由器的延迟时间。注意a可以等于b,此时路径上只有一个路由器。
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!
Hint
100% 测试数据满足N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。对于所有询问满足0<=K<=N 。
思路:树上点更新求第第k大,只是把线段上求第k大放到了树上,直接树剖转换成多条连续的线段,然后就相当于求m个线段加起来的第k大了,把m个线段保存起来,每次把m个线段的左子树的和累加,看是否小于k,小于k,查询m个线段的右子树,直到找到k
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int fa[maxn],num[maxn],dep[maxn],top[maxn],son[maxn],vis[maxn],head[maxn],cnt,cou;
int T[maxn],S[maxn],use[30][maxn],lson[maxn * 50],rson[maxn*50],c[maxn*50],tot,len,a[maxn],b[maxn*2];
int usel[maxn][2],user[maxn][2];
int n,m;
struct Edge
{
int v,next;
}e[maxn * 2];
void add(int a,int b)
{
e[cnt].v = b;
e[cnt].next = head[a];
head[a] = cnt++;
}
void init()
{
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
tot = cou = len = cnt = 0;
}
bool cmp(int a,int b)
{
return a > b;
}
int build(int l,int r)
{
int root = tot++;
c[root] = 0;
if(l != r)
{
int mid = (l + r) >> 1;
lson[root] = build(l,mid);
rson[root] = build(mid + 1,r);
}
return root;
}
int insert1(int root,int pos,int val)
{
int newroot = tot++;
int tmp = newroot;
c[newroot] = c[root] + val;
int l = 0,r = len - 1;
while(l != r)
{
int mid = (l + r) >> 1;
if(pos <= mid)
{
lson[newroot] = tot++;
rson[newroot] = rson[root];
root = lson[root];
newroot = lson[newroot];
r = mid;
}
else
{
lson[newroot] = lson[root];
rson[newroot] = tot++;
root = rson[root];
newroot = rson[newroot];
l = mid + 1;
}
c[newroot] = c[root] + val;
}
return tmp;
}
void hase(int k)
{
sort(b,b+k);
len = unique(b,b+k) - b;
}
int get_hase(int now)
{
return (lower_bound(b,b+len,now) - b);
}
void dfs1(int u,int v,int deep)
{
fa[v] = u;
num[v] = 1;
dep[v] = deep;
int i;
for(i = head[v]; i != -1; i = e[i].next)
{
int end = e[i].v;
if(end == u)
continue;
dfs1(v,end,deep+1);
num[v] += num[end];
if(son[v] == -1 || num[son[v]] < num[end])
{
son[v] = end;
}
}
}
void dfs2(int u,int v)
{
vis[v] = ++cou;
top[v] = u;
T[cou] = insert1(T[cou-1],get_hase(a[v]),1);
if(son[v] != -1)
{
dfs2(u,son[v]);
}
else return;
int i;
for(i = head[v]; i != -1; i = e[i].next)
{
int end = e[i].v;
if(end == fa[v] || end == son[v])
continue;
dfs2(end,end);
}
}
void add(int x,int pos,int val)
{
while(x <= n)
{
S[x] = insert1(S[x],pos,val);
x += (x &(-x));
}
}
struct QQ
{
int k,l,r;
}Q[maxn];
int sum(int x,int now)
{
int tmp = 0;
while(x > 0)
{
tmp += c[lson[use[now][x]]];
x -= (x & (-x));
}
return tmp;
}
void solve(int a1,int b1,int c1)
{
int q,w;
if(c1 == 0)
{
add(vis[a1],get_hase(a[a1]),-1);
add(vis[a1],get_hase(b1),1);
a[a1] = b1;
}
else
{
int t = 0;
int i,j;
q = top[a1], w = top[b1];
int kk = 0;
while(q != w)
{
if(dep[q] < dep[w])
{
swap(q,w);
swap(a1,b1);
}
int ll = vis[q] - 1,rr = vis[a1];
kk += dep[a1] - dep[q] + 1;
usel[t][1] = ll;
usel[t][0] = T[ll];
user[t][1] = rr;
user[t][0] = T[rr];
for(i = ll; i > 0; i -= (i & (-i))) use[t][i] = S[i];
for(i = rr; i > 0; i -= (i & (-i))) use[t][i] = S[i];
t++;
a1 = fa[q];
q = top[a1];
//qurry(ll-1,rr,c);
}
if(dep[a1] > dep[b1])
swap(a1,b1);
int ll = vis[a1] - 1,rr = vis[b1];
kk += dep[b1] - dep[a1] + 1;
if(kk < c1)
{
printf("invalid request!\n");
return;
}
c1 = kk - c1+1;
usel[t][1] = ll;
usel[t][0] = T[ll];
user[t][1] = rr;
user[t][0] = T[rr];
for(i = ll; i > 0; i -= (i & (-i))) use[t][i] = S[i];
for(i = rr; i > 0; i -= (i & (-i))) use[t][i] = S[i];
t++;
int l = 0,r = len - 1;
while(l < r)
{
int mid = (l + r) >> 1;
int ss = 0;
for(i = 0; i < t; i++)
{
ss += sum(user[i][1],i) - sum(usel[i][1],i) + c[lson[user[i][0]]]- c[lson[usel[i][0]]];
}
if(c1 > ss)
{
c1 -= ss;
l = mid + 1;
for(i = 0; i < t; i++)
{
usel[i][0] = rson[usel[i][0]];
for(j = usel[i][1] ; j > 0 ; j -= (j & (-j)))
use[i][j] = rson[use[i][j]];
user[i][0] = rson[user[i][0]];
for(j = user[i][1] ; j > 0 ; j -= (j & (-j)))
use[i][j] = rson[use[i][j]];
}
}
else
{
r = mid;
for(i = 0; i < t; i++)
{
usel[i][0] = lson[usel[i][0]];
user[i][0] = lson[user[i][0]];
for(j = usel[i][1] ; j > 0; j -= (j & (-j)))
use[i][j] = lson[use[i][j]];
for(j = user[i][1] ; j > 0; j -= (j & (-j)))
use[i][j] = lson[use[i][j]];
}
}
}
printf("%d\n",b[l]);
}
}
int main()
{
while(scanf("%d %d",&n,&m) != EOF)
{
int i;
init();
for(i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
b[len++] = a[i];
}
for(i = 1; i < n; i++)
{
int q,w;
scanf("%d %d",&q,&w);
add(q,w);
add(w,q);
}
for(i = 0; i < m; i++)
{
scanf("%d %d %d",&Q[i].k,&Q[i].l,&Q[i].r);
if(Q[i].k == 0)
{
b[len++] = Q[i].r;
}
}
hase(len);
T[0] = build(0,len-1);
dfs1(1,1,1);
dfs2(1,1);
for(i = 0; i < m; i++)
{
solve(Q[i].l,Q[i].r,Q[i].k);
}
}
return 0;
}