【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

时间:2022-10-31 16:14:27

题目描述

M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大的路由器的延迟时间。【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是: 1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。 2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。

输入

第一行为两个整数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

输出

对于每一个第二种询问(k>0),输出一行。包含一个整数为相应的延迟时间。如果路径上的路由器不足k个,则输出信息“invalid request!”(全部小写不包含引号,两个单词之间有一个空格)。

样例输入

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

样例输出

3
2
2
invalid request!


题解

倍增LCA+dfs序+树状数组+主席树

维护一个dfs入栈出栈序,建立主席树,入栈位置将权值位置+1,出栈位置将权值位置-1.。

对于每个询问,转化为x->lca和y->lca的两条链,进而转化为4条路径:1~x + 1~y - 1~lca - 1~fa[lca]。

由于题目带修改,所以需要使用树状数组维护主席树的“前缀和”。然后就可以无脑码了。

需要注意的一点是本题卡空间,所以主席树的插入过程不能每次都新建节点,如果有节点就修改,没有再添加。

#include <cstdio>
#include <algorithm>
#define N 80010
using namespace std;
int w[N] , head[N] , to[N << 1] , next[N << 1] , cnt , fa[N][18] , deep[N] , log[N] , lp[N] , rp[N] , num;
int ls[N * 200] , rs[N * 200] , si[N * 200] , root[N << 1] , tot , A[40] , B[40] , C[40] , D[40] , ta , tb , tc , td;
int v[N << 1] , tv , vk[N] , vx[N] , vy[N];
void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void dfs(int x)
{
int i;
lp[x] = ++num;
for(i = 1 ; (1 << i) <= deep[x] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa[x][0])
fa[to[i]][0] = x , deep[to[i]] = deep[x] + 1 , dfs(to[i]);
rp[x] = ++num;
}
int lca(int x , int y)
{
int i;
if(deep[x] < deep[y]) swap(x , y);
for(i = log[deep[x] - deep[y]] ; ~i ; i -- )
if(deep[x] - deep[y] >= (1 << i))
x = fa[x][i];
if(x == y) return x;
for(i = log[deep[x]] ; ~i ; i -- )
if(deep[x] >= (1 << i) && fa[x][i] != fa[y][i])
x = fa[x][i] , y = fa[y][i];
return fa[x][0];
}
void update(int p , int a , int l , int r , int &x)
{
if(!x) x = ++tot;
si[x] += a;
if(l == r) return;
int mid = (l + r) >> 1;
if(p <= mid) update(p , a , l , mid , ls[x]);
else update(p , a , mid + 1 , r , rs[x]);
}
int query(int k , int l , int r)
{
if(l == r) return l;
int mid = (l + r) >> 1 , sum = 0 , i;
for(i = 1 ; i <= ta ; i ++ ) sum += si[rs[A[i]]];
for(i = 1 ; i <= tb ; i ++ ) sum += si[rs[B[i]]];
for(i = 1 ; i <= tc ; i ++ ) sum -= si[rs[C[i]]];
for(i = 1 ; i <= td ; i ++ ) sum -= si[rs[D[i]]];
if(k <= sum)
{
for(i = 1 ; i <= ta ; i ++ ) A[i] = rs[A[i]];
for(i = 1 ; i <= tb ; i ++ ) B[i] = rs[B[i]];
for(i = 1 ; i <= tc ; i ++ ) C[i] = rs[C[i]];
for(i = 1 ; i <= td ; i ++ ) D[i] = rs[D[i]];
return query(k , mid + 1 , r);
}
else
{
for(i = 1 ; i <= ta ; i ++ ) A[i] = ls[A[i]];
for(i = 1 ; i <= tb ; i ++ ) B[i] = ls[B[i]];
for(i = 1 ; i <= tc ; i ++ ) C[i] = ls[C[i]];
for(i = 1 ; i <= td ; i ++ ) D[i] = ls[D[i]];
return query(k - sum , l , mid);
}
}
int main()
{
int n , q , i , j , x , y , f;
scanf("%d%d" , &n , &q);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &w[i]) , v[++tv] = w[i];
for(i = 2 ; i <= n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x) , log[i] = log[i >> 1] + 1;
dfs(1);
for(i = 1 ; i <= q ; i ++ )
{
scanf("%d%d%d" , &vk[i] , &vx[i] , &vy[i]);
if(!vk[i]) v[++tv] = vy[i];
}
sort(v + 1 , v + tv + 1);
for(tv = 0 , i = 1 ; i <= n + q ; i ++ )
if(v[i] != v[i - 1])
v[++tv] = v[i];
for(i = 1 ; i <= n ; i ++ )
{
w[i] = lower_bound(v + 1 , v + tv + 1 , w[i]) - v;
for(j = lp[i] ; j <= num ; j += j & -j) update(w[i] , 1 , 1 , tv , root[j]);
for(j = rp[i] ; j <= num ; j += j & -j) update(w[i] , -1 , 1 , tv , root[j]);
}
for(i = 1 ; i <= q ; i ++ )
{
if(vk[i])
{
f = lca(vx[i] , vy[i]);
if(deep[vx[i]] + deep[vy[i]] - 2 * deep[f] + 1 < vk[i]) puts("invalid request!");
else
{
ta = tb = tc = td = 0;
for(j = lp[vx[i]] ; j ; j -= j & -j) A[++ta] = root[j];
for(j = lp[vy[i]] ; j ; j -= j & -j) B[++tb] = root[j];
for(j = lp[f] ; j ; j -= j & -j) C[++tc] = root[j];
for(j = lp[fa[f][0]] ; j ; j -= j & -j) D[++td] = root[j];
printf("%d\n" , v[query(vk[i] , 1 , tv)]);
}
}
else
{
vy[i] = lower_bound(v + 1 , v + tv + 1 , vy[i]) - v;
for(j = lp[vx[i]] ; j <= num ; j += j & -j) update(w[vx[i]] , -1 , 1 , tv , root[j]) , update(vy[i] , 1 , 1 , tv , root[j]);
for(j = rp[vx[i]] ; j <= num ; j += j & -j) update(w[vx[i]] , 1 , 1 , tv , root[j]) , update(vy[i] , -1 , 1 , tv , root[j]);
w[vx[i]] = vy[i];
}
}
return 0;
}

【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树的更多相关文章

  1. 【BZOJ】1146&colon; &lbrack;CTSC2008&rsqb;网络管理Network(树链剖分&plus;线段树套平衡树&plus;二分 &sol; dfs序&plus;树状数组&plus;主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...

  2. &lbrack;BZOJ 1146&rsqb; &lbrack;CTSC2008&rsqb;网络管理Network(树状数组&plus;主席树)

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  3. &lbrack;BZOJ1146&rsqb;&lbrack;CTSC2008&rsqb;网络管理Network

    [BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...

  4. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

  5. &lbrack;BZOJ1146&rsqb;&lbrack;CTSC2008&rsqb;网络管理Network&lpar;二分&plus;树链剖分&plus;线段树套平衡树&rpar;

    题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...

  6. BZOJ1146&lbrack;CTSC2008&rsqb;网络管理——出栈入栈序&plus;树状数组套主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条 ...

  7. 2019&period;01&period;13 bzoj1146&colon; &lbrack;CTSC2008&rsqb;网络管理Network(整体二分&plus;树剖)

    传送门 题意简述:给一棵树,支持单点修改,询问路径上两点间第kkk大值. 思路: 读懂题之后立马可以想到序列上带修区间kkk大数的整体二分做法,就是用一个bitbitbit来支持查值. 那么这个题把树 ...

  8. 【bzoj2819】Nim(dfs序&plus;树状数组&sol;线段树)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2819 首先根据SG定理,可得若每堆石子数量的异或值为0,则后手必胜,反之先手必胜.于是 ...

  9. POJ3321&lbrack;苹果树&rsqb; 树状数组&sol;线段树 &plus; dfs序

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions:39452   Accepted: 11694 Descr ...

随机推荐

  1. 混搭&period;NET技术

    新闻 .NET技术+25台服务器怎样支撑世界第54大网站 再度燃起人们对.NET的技术热情.这篇新闻中透露了StackExchange 在技术方面的混搭,这也是我所崇尚的.因此我也在社区里极力推广Mo ...

  2. MVC配置ckeditor&plus;ckfinder

    ckeditor当前使用版本:4.5.8 ckfinder当前使用版本:2.6.0 1.Ckeditor配置简单,直接使用Nuget下载就可 2.下载ckfinder https://cksource ...

  3. String、StringBuffer和StringBuilder的深入解析

    今天闲来无事,整理了下平时记录在印象笔记里的java开发知识点,整理到String,StringBuffer以及StringBuilder的区别时突然又产生了新的疑惑,这些区别是怎么产生的?温故为何能 ...

  4. OC NSArray 数组

    # OC NSArray 数组 NSArray常用方法 获取数组中第一位元素 array.firstObject 获取数组中最后一个元素 array.lastObject 获取数组中指定索引下标的元素 ...

  5. Cocos2d-JS v3&period;0 alpha

    Cocos2d-JS是整合了Cocos2d-html5 v3.0 alpha和Cocos2d-x JSBinding的新JS引擎仓库.整合之后的核心优势在于Html5和JSB的开发流程及API现在变得 ...

  6. Spring整合CXF步骤,Spring实现webService,spring整合WebService

    Spring整合CXF步骤 Spring实现webService, spring整合WebService >>>>>>>>>>>&gt ...

  7. 常用排序算法之——快速排序(C语言&plus;VC6&period;0平台)

    经典排序算法中快速排序具有较好的效率,但其实现思路相对较难理解. #include<stdio.h> int partition(int num[],int low,int high) / ...

  8. Nginx Upstream模块源码分析(上)

    Upstream模块是一个很重要的模块,很多其他模块都会使用它来完成对后端服务器的访问, 达到反向代理和负载均衡的效果.例如Fastcgi.Memcached.SessionSticky等. 如果自己 ...

  9. idea中的language level 介绍

    language level 介绍 其他 IDE 没有看到类似 language level 的设置,所以这个功能应该算是 IntelliJ IDEA 特有的,可是 IntelliJ IDEA 官网也 ...

  10. SqlHelper简单实现(通过Expression和反射)2&period;特性和实体设计

    对于需求中的不要暴露DataTable或DataSet,我想到了设计中常用的对象:实体(Entity),通过实体将数据库中的字段封装成类,这样做不仅使代码更有可读性,维护起来也很方便.同时我自定义了一 ...