BZOJ1146——[CTSC2008]网络管理Network
1、题目大意:就是在动态的树上路径权值第k大。
2、分析:这个就是树链剖分+树套树
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1000000
int Height[M], Top[M], value[M], num[M], Size[M], Fa[M];
int ST_tot, tot;
int son[M], head[M], Next[M];
int n, m;
struct Node{
Node *ch[2];
int cnt, num, r, v;
bool operator < (const Node& rhs) const{
return r < rhs.r;
}
int cmp(int x){
if(x == v) return -1;
if(x < v) return 0;
return 1;
}
void maintain(){
cnt = num;
if(ch[0]) cnt += ch[0] -> cnt;
if(ch[1]) cnt += ch[1] -> cnt;
}
} *root[2 * M], ft[5 * M];
int treap_tot;
inline void treap_rotate(Node* &o, int d){
Node* k = o -> ch[d ^ 1];
o -> ch[d ^ 1] = k -> ch[d];
k -> ch[d] = o;
o -> maintain();
k -> maintain();
o = k;
return;
}
inline void treap_insert(Node* &o, int x){
if(o == NULL){
o = &ft[treap_tot ++];
o -> ch[0] = o -> ch[1] = NULL;
o -> cnt = o -> num = 1;
o -> v = x;
o -> r = rand();
}
else{
int d = o -> cmp(x);
if(d == -1){
o -> num ++;
}
else{
treap_insert(o -> ch[d], x);
if(o < o -> ch[d]) treap_rotate(o, d ^ 1);
}
}
o -> maintain();
}
inline void treap_remove(Node* &o, int x){
int d = o -> cmp(x);
if(d == -1){
if(o -> num > 1) o -> num --;
else if(o -> ch[0] == NULL) o = o -> ch[1];
else if(o -> ch[1] == NULL) o = o -> ch[0];
else {
int d2;
if(o -> ch[0] > o -> ch[1]) d2 = 1;
else d2 = 0;
treap_rotate(o, d2);
treap_remove(o -> ch[d2], x);
}
}
else treap_remove(o -> ch[d], x);
if(o) o -> maintain();
}
inline int treap_lessk(Node* &o, int k){
if(o == NULL) return 0;
int d = o -> cmp(k);
if(d == -1){
int ret = 0;
if(o -> ch[0]) ret += o -> ch[0] -> cnt;
return ret;
}
else if(d == 0){
return treap_lessk(o -> ch[0], k);
}
else{
int ss = o -> num;
if(o -> ch[0]) ss += o -> ch[0] -> cnt;
return treap_lessk(o -> ch[1], k) + ss;
}
}
inline void init(){
Top[1] = 1;
memset(head, -1, sizeof(head));
tot = ST_tot = 0;
}
inline void add(int l, int r, int o, int x, int y, int z){
if(y != -1) treap_remove(root[o], y);
treap_insert(root[o], z);
if(l == r) {
return;
}
int mid = (l + r) / 2;
if(x <= mid) add(l, mid, 2 * o, x, y, z);
else add(mid + 1, r, 2 * o + 1, x, y, z);
}
inline int query(int l, int r, int o, int x, int y, int z){
if(x <= l && r <= y) return root[o] -> cnt - treap_lessk(root[o], z);
int ret = 0, mid = (l + r) / 2;
if(x <= mid) ret += query(l, mid, 2 * o, x, y, z);
if(y > mid) ret += query(mid + 1, r, 2 * o + 1, x, y, z);
return ret;
}
inline void insert(int x, int y){
tot ++;
son[tot] = y;
Next[tot] = head[x];
head[x] = tot;
}
inline void dfs1(int x, int fa, int height){
Fa[x] = fa;
Height[x] = height;
Size[x] = 1;
for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa){
dfs1(son[i], x, height + 1);
Size[x] += Size[son[i]];
}
}
inline void dfs2(int x, int fa){
++ ST_tot;
num[x] = ST_tot;
add(1, n, 1, ST_tot, -1, value[x]);
int o = 0, ss = 0;
for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa){
if(Size[son[i]] > ss){
ss = Size[son[i]];
o = i;
}
}
if(o != 0){
Top[son[o]] = Top[x];
dfs2(son[o], x);
}
for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa && o != i){
Top[son[i]] = son[i];
dfs2(son[i], x);
}
}
inline void real_add(int x, int y){
add(1, n, 1, num[x], value[x], y);
value[x] = y;
}
inline int check(int x, int y, int k){
int ret = 0;
while(Top[x] != Top[y]){
if(Height[Top[x]] < Height[Top[y]]) swap(x, y);
ret += query(1, n, 1, num[Top[x]], num[x], k);
x = Fa[Top[x]];
}
if(Height[x] < Height[y]) swap(x, y);
ret += query(1, n, 1, num[y], num[x], k);
return ret;
}
inline int real_query(int x, int y, int k){
int l = -1, r = 100000000;
while(l < r){
int mid = (l + r) / 2;
if(mid == l) mid ++;
if(check(x, y, mid) >= k) l = mid;
else r = mid - 1;
}
if(l == -1) return -1;
return l;
}
int main(){
scanf("%d%d", &n, &m);
init();
for(int i = 1; i <= n; i ++) scanf("%d", &value[i]);
for(int i = 1; i < n; i ++){
int x, y;
scanf("%d%d", &x, &y);
insert(x, y);
insert(y, x);
}
dfs1(1, 0, 1);
dfs2(1, 0);
for(int i = 1; i <= m; i ++){
int k, x, y;
scanf("%d%d%d", &k, &x, &y);
if(k == 0){
real_add(x, y);
}
else if(k > 0){
int qq = real_query(x, y, k);
if(qq == -1){
printf("invalid request!\n");
}
else{
printf("%d\n", qq);
}
}
}
return 0;
}
BZOJ1146——[CTSC2008]网络管理Network的更多相关文章
- [BZOJ1146][CTSC2008]网络管理Network
[BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...
- BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
- 2019.01.13 bzoj1146: [CTSC2008]网络管理Network(整体二分+树剖)
传送门 题意简述:给一棵树,支持单点修改,询问路径上两点间第kkk大值. 思路: 读懂题之后立马可以想到序列上带修区间kkk大数的整体二分做法,就是用一个bitbitbit来支持查值. 那么这个题把树 ...
- 【树上莫队】【带修莫队】【权值分块】bzoj1146 [CTSC2008]网络管理Network
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...
- 【树链剖分】【函数式权值分块】bzoj1146 [CTSC2008]网络管理Network
裸题,直接上.复杂度O(n*sqrt(n)*log(n)). //Num[i]表示树中的点i在函数式权值分块中对应的点 //Map[i]表示函数式权值分块中的点i在树中对应的点 #include< ...
- 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树
[BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...
- BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 3522 Solved: 1041[Submi ...
- 【BZOJ-1146】网络管理Network DFS序 + 带修主席树
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 3495 Solved: 1032[Submi ...
随机推荐
- CSS3-column分栏
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 什么是FOUC?如何避免FOUC?
因为在看一些面试题,所以接触到了这个词 FOUC 什么叫做 FOUC 浏览器样式闪烁 如果使用import方法对css进行导入,会导致某些页面在Windows 下的Internet Explorer出 ...
- 在JavaScript中,arguments是对象的一个特殊属性。
arguments对象 function函数的内置参数的"数组"/"集合":同时arguments对象就像数组,但是它却不是数组. 常用属性: 1.length ...
- nginx https性能优化
影响HTTPS速度的主要原因:秘钥交换算法 常见的密钥交换算法有 RSA,ECDHE,DH,DHE 等算法.它们的特性如下: RSA:算法实现简单,诞生于 1977 年,历史悠久,经过了长时间的破解测 ...
- 深入浅出MyBatis
参考文献:深入浅出MyBatis MyBatis功能架构图: MyBatis内部原理流程图: 详情见:深入浅出MyBatis
- 如何查看crontab的日志记录
在Unix和类Unix的操作系统之中,crontab命令常用于设置周期性被执行的指令,也可以理解为设置定时任务. crontab中的定时任务有时候没有成功执行,什么原因呢?这时就需要去日志里去分析一下 ...
- asp+mysql__不同类型用户登录
未防注入//0.0 /***这里代码应用场景为多类用户登录,根据用户选择不同的单选按钮判断用户登录的类型,*从而进行不同的数据表进行判断,用户的用户名和密码是否正确.*/ public partial ...
- Ecshop商品促销时间精确到小时分钟和秒的设置方法 调用时间
第一步:找到admin/tempate/good_info.htm文件 把<input name="selbtn1" type="button" id=& ...
- thinkphp传递参数
php文件输出 U() 跳转地址, echo U('Index/index',array('uid'=>1,'username'=>'wang','time'=>165465121) ...
- localdomain的linux域
both和and的区别? both强调(两者)都,用于肯定语气, and字面意思是"和,而且",是用于表示并列关系的句子,通常位于最后两个人或物之间,将将人物串联起来 如: thi ...