$ \color{#0066ff}{ 题目描述 }$

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

【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是:

  1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。
  2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。

\(\color{#0066ff}{输入格式}\)

第一行为两个整数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,此时路径上只有一个路由器。

\(\color{#0066ff}{输出格式}\)

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

\(\color{#0066ff}{输入样例}\)

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

\(\color{#0066ff}{输出样例}\)

3
2
2
invalid request!

\(\color{#0066ff}{数据范围与提示}\)

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

\(\color{#0066ff}{题解}\)

单点修改,树链查询。。。树剖

查询第k大?数据范围80000? 树套树!

直接把树剖的线段树改成线段树套平衡树,二分找第k大,复杂度\(O(qlog^4n)\)能卡过!

注意查的是第k大不是第k小!!!

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
LL read() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
template<class T> bool chkmax(T &a, const T &b) { return a < b? a = b, 1 : 0; }
template<class T> bool chkmin(T &a, const T &b) { return b < a? a = b, 1 : 0; }
const int maxn = 1e5 + 10;
int dfn[maxn], nfd[maxn], top[maxn], son[maxn];
int siz[maxn], fa[maxn], dep[maxn], cnt, val[maxn];
struct Splay {
protected:
struct node {
node *ch[2], *fa;
int siz, val;
node(int siz = 0, int val = 0): siz(siz), val(val) { fa = ch[0] = ch[1] = NULL; }
void upd() { siz = (ch[0]? ch[0]->siz : 0) + (ch[1]? ch[1]->siz : 0) + 1; }
bool isr() { return this == fa->ch[1]; }
int rk() { return ch[0]? ch[0]->siz + 1 : 1; }
}*root;
void rot(node *x) {
node *y = x->fa, *z = y->fa;
bool k = x->isr(); node *w = x->ch[!k];
if(y != root) z->ch[y->isr()] = x;
else root = x;
(x->ch[!k] = y)->ch[k] = w;
(y->fa = x)->fa = z;
if(w) w->fa = y;
y->upd(), x->upd();
}
void splay(node *o) {
while(o != root) {
if(o->fa != root) rot(o->isr() ^ o->fa->isr()? o : o->fa);
rot(o);
}
}
node *merge(node *fa, node *x, node *y) {
if(x) x->fa = fa;
if(y) y->fa = fa;
if(!x || !y) return x? x : y;
if(rand() & 1) return x->ch[1] = merge(x, x->ch[1], y), x->upd(), x;
else return y->ch[0] = merge(y, x, y->ch[0]), y->upd(), y;
}
public:
Splay() { root = NULL; }
void ins(int val) {
if(!root) return (void)(root = new node(1, val));
node *o = root, *fa = NULL;
while(o) fa = o, o = o->ch[val > o->val];
fa->ch[val > fa->val] = o = new node(1, val);
o->fa = fa, splay(o);
}
void del(int val) {
node *o = root;
while(o && o->val != val) o = o->ch[val > o->val];
if(!o) return;
splay(o);
root = merge(NULL, o->ch[0], o->ch[1]);
}
int rnk(int val) {
int num = 0; node *o = root;
while(o) {
if(o->val < val) num += o->rk(), o = o->ch[1];
else o = o->ch[0];
}
return num;
}
};
struct Segment_Tree {
protected:
struct node {
node *ch[2];
int l, r;
Splay T;
node(int l = 0, int r = 0): l(l), r(r) { ch[0] = ch[1] = NULL; }
int mid() { return (l + r) >> 1; }
}*root;
void build(node *&o, int l, int r) {
o = new node(l, r);
for(int i = l; i <= r; i++) o->T.ins(val[nfd[i]]);
if(l == r) return;
build(o->ch[0], l, o->mid()); build(o->ch[1], o->mid() + 1, r);
}
int query(node *o, int l, int r, int val) {
if(l <= o->l && o->r <= r) return o->T.rnk(val);
int ans = 0;
if(l <= o->mid()) ans += query(o->ch[0], l, r, val);
if(r > o->mid()) ans += query(o->ch[1], l, r, val);
return ans;
}
public:
void change(int pos, int old, int now) {
node *o = root;
while(1) {
o->T.del(old), o->T.ins(now);
if(o->l == o->r) break;
if(pos <= o->mid()) o = o->ch[0];
else o = o->ch[1];
}
}
void init(int n) { build(root, 1, n); }
int query(int l, int r, int val) { return query(root, l, r, val); }
}T;
int n, m;
std::vector<int> G[maxn];
void dfs1(int x, int f) {
dep[x] = dep[fa[x] = f] + (siz[x] = 1);
for(auto to : G[x]) {
if(to == f) continue;
dfs1(to, x);
siz[x] += siz[to];
if(siz[to] > siz[son[x]]) son[x] = to;
}
}
void dfs2(int x, int t) {
top[nfd[dfn[x] = ++cnt] = x] = t;
if(son[x]) dfs2(son[x], t);
for(auto to : G[x]) if(!dfn[to]) dfs2(to, to);
}
void predoit() { dfs1(1, 0), dfs2(1, 1), T.init(n); }
void change(int x, int y) {
T.change(dfn[x], val[x], y);
val[x] = y;
} int getans(int x, int y, int val) {
//printf("now is getans(%d -> %d, lower %d), ", x, y, val);
int ans = 0, fx = top[x], fy = top[y];
while(fx != fy) {
if(dep[fx] < dep[fy]) std::swap(fx, fy), std::swap(x, y);
ans += T.query(dfn[fx], dfn[x], val);
fx = top[x = fa[fx]];
}
if(dep[x] < dep[y]) std::swap(x, y);
ans += T.query(dfn[y], dfn[x], val);
//printf("ans = %d\n", ans);
return ans;
}
int getnum(int x, int y) {
int ans = 0, fx = top[x], fy = top[y];
while(fx != fy) {
if(dep[fx] < dep[fy]) std::swap(fx, fy), std::swap(x, y);
ans += (dfn[x] - dfn[fx] + 1);
fx = top[x = fa[fx]];
}
if(dep[x] < dep[y]) std::swap(x, y);
return ans + (dfn[x] - dfn[y] + 1);
} void kthpath(int x, int y, int k) {
int num = getnum(x, y);
if(num < k) return (void)(puts("invalid request!"));
k = num - k + 1;
int l = 0, r = 1e8, ans = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if(getans(x, y, mid) + 1 <= k) ans = mid, l = mid + 1;
else r = mid - 1;
}
printf("%d\n", ans);
}
int main() {
n = read(), m = read();
for(int i = 1; i <= n; i++) val[i] = read();
int x, y, k;
for(int i = 1; i < n; i++) {
x = read(), y = read();
G[x].push_back(y);
G[y].push_back(x);
}
predoit();
while(m --> 0) {
k = read(), x = read(), y = read();
if(!k) change(x, y);
else kthpath(x, y, k);
}
return 0;
}

P4175 [CTSC2008]网络管理 树剖+树套树的更多相关文章

  1. 洛谷 P4175 [CTSC2008]网络管理 解题报告

    P4175 [CTSC2008]网络管理 题目描述 带修改树上链的第\(k\)大 输入输出格式 输入格式: 第一行为两个整数\(N\)和\(Q\),分别表示路由器总数和询问的总数. 第二行有\(N\) ...

  2. 【BZOJ-1452】Count 树状数组 套 树状数组

    1452: [JSOI2009]Count Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1769  Solved: 1059[Submit][Stat ...

  3. 【BZOJ】1047: [HAOI2007]理想的正方形(单调队列/~二维rmq+树状数组套树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1047 树状数组套树状数组真心没用QAQ....首先它不能修改..而不修改的可以用单调队列做掉,而且更 ...

  4. BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)

    BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...

  5. BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序

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

  6. 2017多校第9场 HDU 6162 Ch’s gift 树剖加主席树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162 题意:给出一棵树的链接方法,每个点都有一个数字,询问U->V节点经过所有路径中l < ...

  7. HDU 6162 Ch’s gift (树剖 + 离线线段树)

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  8. 洛谷P4175 - [CTSC2008]网络管理

    Portal Description 给出一棵\(n(n\leq8\times10^4)\)个点的带点权的树,进行\(m(m\leq8\times10^4)\)次操作,操作有两种: 修改一个点的点权. ...

  9. P4175 [CTSC2008]网络管理

    如果没有修改就是简单主席树,有了修改的话因为主席树维护的是到根的一段路径,所以修改操作会修改子树,也就是连续的一段dfn 所以显然树套树一波就没了 极其好写 #include<bits/stdc ...

随机推荐

  1. 基于Linux服务器的性能分析与优化

    作为一名Linux系统管理员,最主要的工作是优化系统配置,使应用在系统上以最优的状态运行,但硬件问题.软件问题.网络环境等的复杂性和多变性,导致了对系统的优化变得异常复杂,如何定位性能问题出在哪个方面 ...

  2. fastDFS配置及日志查看 所遇到的问题

    FastDFS的配置文件在/usr/local/webserver/fastdfs/etc目录下,其中包括 client.conf    客户端上传配置文件 storage.conf    文件存储服 ...

  3. windows下怎么安装protobuf for python

    首先从google上下载protobuf-3.0.0.zip和protoc-3.0.0-win32.zip,然后把protoc-3.0.0-win32.zip里的protoc.exe放到protobu ...

  4. robotframework中文显示乱码

    问题描述:接口.数据库返回信息有中文的时候会显示unicode的样式,如图 解决方法: 1.robotframework为3.0.X 2.找到Python安装目录下的\Lib\site-package ...

  5. Use formatter to format your JAVA code

    In order to make the codes looks unified and make it easy to understand, it's better to use the same ...

  6. Auto Encoder

    对自编码器的理解: 对于给定的原始输入x,让网络自动找到一种编码方式(特征提取,原始数据的另一种表达),使其解码后的输出x'尽可能复现原始输入x. 知乎参考:https://www.zhihu.com ...

  7. ASP.NET MVC 跨controller函数调用

    var controller = DependencyResolver.Current.GetService<ControllerClassName>(); controller.User ...

  8. Oracle RMAN-06023 和ORA-19693错误

    在将一个0级备份的数据库还原到其它机器上时,首先遇到了RMAN-06023然后遇到ORA-19693错误,错误发生的环境和内容大致如下: 数据库版本: SQL> select * from v$ ...

  9. C++11学习笔记之三lamda表达式,std::function, std::bind

    //lamda //first lamda [] {}; // second lamda []() //or no need () when paramater is null { std::cout ...

  10. 认证服务号Thinkphp微信支付

    公众号配置 1.微信支付过程中需要获取用户的openid,所以,仍需填写 网页授权域名 2.微信支付授权目录  Thinkphp目录格式为www.xxx.cn/home/wxpay/ 这里目录不能填写 ...