$ \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. 117. Populating Next Right Pointers in Each Node II 计算右边的附属节点

    [抄题]: Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNod ...

  2. Result Grouping / Field Collapsing-结果分组

    WiKi:http://wiki.apache.org/solr/FieldCollapsing Introduction 字段折叠和结果分组是考虑相同solr功能的两种不同的方式. 字段折叠折叠一组 ...

  3. 15- 1 << k 时的益出

    扩展GCD-时间复杂性 题目: 计算循环语句的执行频次 for (i = A; i != B; i += C) x += 1;其中A, B, C, i都是k位无符号整数. 输入: A B C k, 其 ...

  4. 14-python登入教务网(python+bs4)

    用request先得到到session对象,用其去放送请求,会自动保存cookie. 模拟有验证码的登入步骤: 1.发送请求登入页面: 2.分析验证码的地址,以及要将登入请求发往的地址(可以先输入错的 ...

  5. OpenCV学习记录(二):自己训练haar特征的adaboost分类器进行人脸识别 标签: 脸部识别opencv 2017-07-03 21:38 26人阅读

    上一篇文章中介绍了如何使用OpenCV自带的haar分类器进行人脸识别(点我打开). 这次我试着自己去训练一个haar分类器,前后花了两天,最后总算是训练完了.不过效果并不是特别理想,由于我是在自己的 ...

  6. Ext.data.association.hasMany一对多模型使用示例

    来自<sencha touch权威指南>第11章,323页开始 --------------------------------------------------- index.html ...

  7. json日期格式话

    // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年(y)可以用 1-4 个占 ...

  8. Linux 上安装 rlwrap

    1.安装rlwrap的初衷; 2.安装rlwrap工具和遇到的问题; 3.使用rlwrap 工具; 1.安装rlwrap的初衷: 在Windows 下使用SQLPLUS都是可以使用上下左右方向键前后左 ...

  9. 【转载】Mysql中的Btree与Hash索引比较

    转载地址:http://www.jb51.net/article/62533.htm 这篇文章主要介绍了Mysql中的Btree与Hash索引比较,本文起讲解了B-Tree 索引特征.Hash 索引特 ...

  10. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(12):XML配置自动扫描包,自动加载*.properties文件

    一.XML和注解组合使用 前几篇的测试案例都是在Java类中配置,现在换一种使用方式,在XML中配置,使Spring IoC容器在启动之后自动去扫描配置的包路径,扫描加载指定路径下的propertie ...