[BZOJ1146][CTSC2008]网络管理Network

试题描述

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!”(全部小写不包含引号,两个单词之间有一个空格)。

输入示例


输出示例


invalid request!

数据规模及约定

见“输入

题解

树链剖分套线段树套 treap + 二分。4 个 log 爽上天。

本来打了个 1A 的代码,发现它让求第 k “大”而非第 k “小”,而样例给的都是中位数!!!!于是拿黄学长的代码调了半天总是有错发现他数组开小了(那居然还能过!)。我调啊调啊调,改啊改啊改。。。一个上午过去,终于 A 掉了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 80010
#define maxm 160010
#define maxnode 5440010
struct Node {
int v, r, siz;
Node() {}
Node(int _, int __): v(_), r(__) {}
} ns[maxnode];
int ToT, fa[maxnode], ch[2][maxnode];
void maintain(int o) {
if(!o) return ;
ns[o].siz = 1;
for(int i = 0; i < 2; i++) if(ch[i][o])
ns[o].siz += ns[ch[i][o]].siz;
return ;
}
void rotate(int u) {
int y = fa[u], z = fa[y], l = 0, r = 1;
if(z) ch[ch[1][z]==y][z] = u;
if(ch[1][y] == u) swap(l, r);
fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
ch[l][y] = ch[r][u]; ch[r][u] = y;
maintain(y); maintain(u);
return ;
}
void insert(int& o, int v) {
if(!o) {
ns[o = ++ToT] = Node(v, rand());
return maintain(o);
}
bool d = v > ns[o].v;
insert(ch[d][o], v); fa[ch[d][o]] = o;
if(ns[ch[d][o]].r > ns[o].r) {
int t = ch[d][o];
rotate(t); o = t;
}
return maintain(o);
}
void del(int& o, int v) {
if(!o) return ;
if(ns[o].v == v) {
if(!ch[0][o] && !ch[1][o]) o = 0;
else if(!ch[0][o]) {
int t = ch[1][o]; fa[t] = fa[o]; o = t;
}
else if(!ch[1][o]) {
int t = ch[0][o]; fa[t] = fa[o]; o = t;
}
else {
bool d = ns[ch[1][o]].r > ns[ch[0][o]].r;
int t = ch[d][o]; rotate(t); o = t;
del(ch[d^1][o], v);
}
}
else {
bool d = v > ns[o].v;
del(ch[d][o], v);
}
return maintain(o);
}
int Find(int o, int v) {
if(!o) return 0;
int rs = ch[1][o] ? ns[ch[1][o]].siz : 0;
if(v <= ns[o].v) return rs + 1 + Find(ch[0][o], v);
return Find(ch[1][o], v);
} int rt[maxn<<2], ql, qr, val[maxn];
void add(int L, int R, int o) {
insert(rt[o], val[ql]);
if(L == R) return ;
int M = L + R >> 1, lc = o << 1, rc = lc | 1;
if(ql <= M) add(L, M, lc);
else add(M+1, R, rc);
return ;
}
void update(int L, int R, int o, int x) {
del(rt[o], val[ql]); insert(rt[o], x);
if(L == R) return ;
int M = L + R >> 1, lc = o << 1, rc = lc | 1;
if(ql <= M) update(L, M, lc, x);
else update(M+1, R, rc, x);
return ;
}
int query(int L, int R, int o, int x) {
if(ql <= L && R <= qr) return Find(rt[o], x);
int M = L + R >> 1, lc = o << 1, rc = lc | 1, ans = 0;
if(ql <= M) ans += query(L, M, lc, x);
if(qr > M) ans += query(M+1, R, rc, x);
return ans;
} int n, m, head[maxn], next[maxm], to[maxm], inv[maxn];
void AddEdge(int a, int b) {
to[++m] = b; next[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; next[m] = head[a]; head[a] = m;
return ;
}
int pa[maxn], son[maxn], dep[maxn], siz[maxn], top[maxn], W[maxn], ww;
void build(int u) {
siz[u] = 1;
for(int e = head[u]; e; e = next[e]) if(to[e] != pa[u]) {
pa[to[e]] = u; dep[to[e]] = dep[u] + 1;
build(to[e]);
siz[u] += siz[to[e]];
if(!son[u] || siz[son[u]] < siz[to[e]]) son[u] = to[e];
}
return ;
}
void gett(int u, int tp) {
W[u] = ++ww; top[u] = tp;
if(son[u]) gett(son[u], tp);
for(int e = head[u]; e; e = next[e]) if(to[e] != pa[u] && to[e] != son[u])
gett(to[e], to[e]);
return ;
}
int que(int a, int b, int x) {
int f1 = top[a], f2 = top[b], ans = 0;
while(f1 != f2) {
if(dep[f1] < dep[f2]) swap(f1, f2), swap(a, b);
ql = W[f1]; qr = W[a];
ans += query(1, n, 1, x);
a = pa[f1]; f1 = top[a];
}
if(dep[a] < dep[b]) swap(a, b);
ql = W[b]; qr = W[a];
return ans + query(1, n, 1, x);
} int main() {
n = read(); int q = read();
for(int i = 1; i <= n; i++) inv[i] = read() + 1;
for(int i = 1; i < n; i++) {
int a = read(), b = read();
AddEdge(a, b);
}
build(1); gett(1, 1);
for(int i = 1; i <= n; i++) val[W[i]] = inv[i];
for(int i = 1; i <= n; i++) ql = i, add(1, n, 1);
while(q--) {
int k = read(), a = read(), b = read();
if(!k) ql = W[a], update(1, n, 1, b + 1), val[W[a]] = b + 1;
else {
int l = 0, r = 100000002;
while(r - l > 1) {
int mid = l + r >> 1;
if(que(a, b, mid) < k) r = mid; else l = mid;
}
if(l) printf("%d\n", l - 1); else puts("invalid request!");
}
} return 0;
}

代码是挺短的。。。

[BZOJ1146][CTSC2008]网络管理Network的更多相关文章

  1. BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...

  2. [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)

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

  3. BZOJ1146——[CTSC2008]网络管理Network

    1.题目大意:就是在动态的树上路径权值第k大. 2.分析:这个就是树链剖分+树套树 #include <cstdio> #include <cstdlib> #include ...

  4. 2019.01.13 bzoj1146: [CTSC2008]网络管理Network(整体二分+树剖)

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

  5. 【树上莫队】【带修莫队】【权值分块】bzoj1146 [CTSC2008]网络管理Network

    #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...

  6. 【树链剖分】【函数式权值分块】bzoj1146 [CTSC2008]网络管理Network

    裸题,直接上.复杂度O(n*sqrt(n)*log(n)). //Num[i]表示树中的点i在函数式权值分块中对应的点 //Map[i]表示函数式权值分块中的点i在树中对应的点 #include< ...

  7. 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树

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

  8. BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[Submi ...

  9. 【BZOJ-1146】网络管理Network DFS序 + 带修主席树

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3495  Solved: 1032[Submi ...

随机推荐

  1. Path Sum II

    Path Sum II Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals ...

  2. AppBox升级进行时 - 扁平化的权限设计

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. AppBox v2.0中的权限实现 AppBox v2.0中权限管理中涉及三个 ...

  3. Spark在Ubuntu中搭建开发环境

    一.在Windows7中安装Ubuntu双系统 工具/原料   windows7 64位 ubuntu 16.04 32位 UltraISO最新版(用来将镜像文件烤到U盘中) 空U盘(若有文件,请先备 ...

  4. 【jQuery】scroll 滚动到顶部

    Jquery 实现页面滚动到顶端 $(document).ready(function () { // 滚动窗口来判断按钮显示或隐藏 $(window).scroll(function () { // ...

  5. C#字符串操作 取文本左边 取文本右边 取文本中间 取文本中间到List集合 指定文本倒序

    /// <summary> /// 取文本左边内容 /// </summary> /// <param name="str">文本</pa ...

  6. css实现了hover显示title的效果

    <div data-title="hello, world">hello...</div> <style> div { position: re ...

  7. 每个程序员都会的35个jQuery小技巧!

    1. 禁止右键点击$(document).ready(function(){ $(document).bind("contextmenu",function(e){ return ...

  8. Mysql索引PRIMARY、NORMAL、UNIQUE、FULLTEXT 区别和使用场合

    索引 数据库的索引就像一本书的目录,能够加快数据库的查询速度. MYSQL索引有四种PRIMARY.INDEX.UNIQUE.FULLTEXT, 其中PRIMARY.INDEX.UNIQUE是一类,F ...

  9. C#接口和抽象类的区别

    大家都容易把这两者搞混,我也一样,在听李建忠老师的设计模式时,他也老把抽象类说成接口,弄的我就更糊涂了,所以找了些网上的资料.      一.抽象类:      抽象类是特殊的类,只是不能被实例化:除 ...

  10. 用 CSS 隐藏页面元素

    用 CSS 隐藏页面元素有许多种方法.你可以将 opacity 设为 0 将 visibility 设为 hidden 将 display 设为 none 将 position 设为 absolute ...