[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. Slam(即时定位与地图构建) 知识篇

    Slam即时定位与地图构建 技术解释 同步定位与地图构建(SLAM或Simultaneous localization and mapping)是一种概念:希望机器人从未知环境的未知地点出发,在运动过 ...

  2. [自学总结] Unity5.3 API 之 Audio Mixer

    unity5.3 - API - class AudioMixer 和 class AudioMixerGrou问题:之前版本声音的渐入渐出太生硬,声音的特效需要自己手动编写.分析:5.0版本重大更新 ...

  3. FILE不是C语言关键字

    FILE不是C语言关键字,只是标准C中的标准输入输出中定义的一个新的数据类型 stdio.htypedef struct _iobuf{ char* _ptr; int _cnt; char* _ba ...

  4. Oracle 中的分析函数

    Oracle常用分析函数介绍(排名函数+窗口函数) 2014年11月30日 ⁄ 数据库 ⁄ 共 3903字 ⁄ 暂无评论 ⁄ 阅读 7,772 次 评级函数 常见评级函数如下: RANK():返回数据 ...

  5. C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 基于数据库资源的多语言实现

    以前的开发平台里,是用xml语言包实现了多语言功能,现在新的平台里进行了调整,把多语言包资源放在数据库表里实现了. 我们系统预留了多语言的配置全局变量.可以通过配置这个参数达到切换多语言的目的 我们在 ...

  6. 安卓开发:一种快速提取安卓app的UI图标资源的方法

    在做安卓设计时,找美工设计界面的漂亮图标是必不可少的,但是对于一个初创团队来说,请一个UI的成本其实也挺高的,此时对于一个偏技术的产品经理来说,从其他成熟的产品的apk中提取图标就是一个很便捷的方法, ...

  7. Ionic中使用Chart.js进行图表展示以及在iOS/Android中的性能差异

    Angular Chart 简介 在之前的文章中介绍了使用 Ionic 开发跨平台(iOS & Android)应用中遇到的一些问题的解决方案. 在更新0.1.3版本的过程中遇到了需要使用图表 ...

  8. 可变长子网掩码 VLSM

    2014-05-05 17:26:08 标签:IP地址 路由器 技术部 路由表 长子 VLSM的介绍: VLSM(VLSM(Variable Length Subnetwork Mask,可变长子网掩 ...

  9. MyISAM 和InnoDB 的区别.(存储,索引, 事务, 锁)

    MyISAM类型的表强调的是性能,但是不支持事务.及外部键等高级功能. MySQL默认采用的是MyISAM. MyISAM不支持事务,而InnoDB支持.InnoDB的AUTOCOMMIT默认是打开的 ...

  10. 软件工程(FZU2015)赛季得分榜,第9回合

    目录 第一回合 第二回合 第三回合 第四回合 第五回合 第6回合 第7回合 第8回合 第9回合 第10回合 第11回合 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分: 团队项目分 ...