机房某大佬告诉我,一条链在全局线段树中的区间最多有$log$段

因此同样的,代表不在这条链上的区间同样只有$log$段

对这$log$段区间进行维护即可

为了能够删除,在线段树的每个节点暴力维护一个堆

每次加入一条链时,在这$log$段区间上暴力加入元素

每次删除一条链时,暴力删除元素

询问时,对所有经过的区间进行查询

注意堆标记不要下传,直接标记永久化就行

插入 / 删除复杂度单次$O(\log^3 n)$

查询复杂度单次$O(log n)$

空间复杂度$O(n \log^2 n)$

注:$bzoj$会$MLE$....不要轻易尝试

注2:打了30多min,好累啊.....

注3:大家还是去学习$O(n \log n)$的优秀做法吧...

#include <map>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; extern inline char gc() {
static char RR[], *S = RR + , *T = RR + ;
if(S == T) fread(RR, , , stdin), S = RR;
return *S ++;
}
inline int read() {
int p = , w = ; char c = gc();
while(c > '' || c < '') { if(c == '-') w = -; c = gc(); }
while(c >= '' && c <= '') p = p * + c - '', c = gc();
return p * w;
} #define ri register int
#define sid 200050 int n, m, cnp, id;
int nxt[sid], node[sid], cap[sid]; inline void addedge(int u, int v) {
nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v;
nxt[++ cnp] = cap[v]; cap[v] = cnp; node[cnp] = u;
} int U[sid], V[sid], W[sid];
int dfn[sid], sz[sid], dep[sid];
int son[sid], anc[sid], fa[sid]; #define cur node[i]
void dfs(int o) {
sz[o] = ;
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa[o]) {
dep[cur] = dep[o] + ; fa[cur] = o; dfs(cur); sz[o] += sz[cur];
if(sz[cur] > sz[son[o]]) son[o] = cur;
}
} void dfs(int o, int ac) {
dfn[o] = ++ id; anc[o] = ac;
if(!son[o]) return; dfs(son[o], ac);
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa[o] && cur != son[o]) dfs(cur, cur);
} struct Heap {
priority_queue <int> q1, q2;
inline void ins(int x) { q1.push(x); }
inline void era(int x) { q2.push(x); }
inline int top() {
while() {
if(q2.empty()) return q1.top();
if(q1.top() == q2.top()) q1.pop(), q2.pop();
else return q1.top();
}
}
} t[sid << ]; #define ls (o << 1)
#define rs (o << 1 | 1) void build(int o, int l, int r) {
t[o].ins(-); if(l == r) return;
int mid = (l + r) >> ;
build(ls, l, mid); build(rs, mid + , r);
} void upd(int o, int l, int r, int ml, int mr, int v, int opt) {
if(ml > mr) return;
if(ml > r || mr < l) return;
if(ml <= l && mr >= r) { if(opt) t[o].ins(v); else t[o].era(v); return; }
int mid = (l + r) >> ;
upd(ls, l, mid, ml, mr, v, opt);
upd(rs, mid + , r, ml, mr, v, opt);
} int qry(int o, int l, int r, int ml, int mr) {
if(ml > r || mr < l) return -;
if(ml <= l && mr >= r) return t[o].top();
int mid = (l + r) >> ;
return max(t[o].top(), max(qry(ls, l, mid, ml, mr), qry(rs, mid + , r, ml, mr)));
} struct Seg {
int l, r;
friend bool operator < (Seg a, Seg b)
{ return a.l < b.l; }
}; vector <Seg> re; void Upd(int u, int v, int w, int opt) {
re.clear();
int pu = anc[u], pv = anc[v];
while(pu != pv) {
if(dep[pu] < dep[pv]) swap(u, v), swap(pu, pv);
re.push_back( { dfn[pu], dfn[u] } );
u = fa[pu]; pu = anc[u];
}
if(dep[u] < dep[v]) swap(u, v);
re.push_back( { dfn[v], dfn[u] } );
re.push_back( { , } );
re.push_back( { n + , n + } );
sort(re.begin(), re.end());
for(ri i = ; i < re.size(); i ++)
upd(, , n, re[i - ].r + , re[i].l - , w, opt);
} int main() {
n = read(); m = read();
for(ri i = ; i < n; i ++) {
int u = read(), v = read();
addedge(u, v);
}
dfs(); dfs(, ); build(, , n);
for(ri i = ; i <= m; i ++) {
int opt = read(), u, v, w;
if(opt == ) {
u = read(); v = read(); w = read();
U[i] = u; V[i] = v; W[i] = w; Upd(u, v, w, );
}
if(opt == ) u = read(), Upd(U[u], V[u], W[u], );
if(opt == ) u = read(), printf("%d\n", qry(, , n, dfn[u], dfn[u]));
}
return ;
}

luoguP3250 [HNOI2016]网络 树链剖分 + 堆的更多相关文章

  1. BZOJ4538:[HNOI2016]网络(树链剖分,堆)

    Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做 一条树边.两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有 ...

  2. [HNOI2016]网络 树链剖分,堆

    [HNOI2016]网络 LG传送门 表示乱搞比正解难想. 整体二分很好想吧. 但是为了好写快乐,我们选择三个\(\log\)的乱搞. 先树剖,线段树套堆维护区间最大值.对于一次修改,如果是插入,就把 ...

  3. [HNOI2016]网络 [树链剖分,可删除堆]

    考虑在 |不在| 这条链上的所有点上放上一个 \(x\),删除也是,然后用可删除堆就随便草掉了. // powered by c++11 // by Isaunoya #pragma GCC opti ...

  4. 【BZOJ4538】【HNOI2016】网络(树链剖分,线段树,堆)

    题目链接,我是真的懒得调题目的格式... 题解 树链剖分搞一下LCA 把线段树弄出来 这只是形式上的线段树 本质上是维护一段区间的一个堆 每次把堆插入节点, 询问的时候查询线段树上的堆的最大值就行了 ...

  5. 2019.01.13 bzoj4538: [Hnoi2016]网络(树链剖分)

    传送门 树链剖分一眼题. 题意简述: 给定一棵树,有三种操作: 加入一条路径 删除一条已加入的路径 询问不过一个点x的路径的最大值. 思路: 直接树链剖分维护答案. 因为询问的事不过点xxx的最大值, ...

  6. 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp

    题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...

  7. 焦作网络赛E-JiuYuanWantstoEat【树链剖分】【线段树】

    You ye Jiu yuan is the daughter of the Great GOD Emancipator. And when she becomes an adult, she wil ...

  8. CF487E Tourists(圆方树+树链剖分+multiset/可删堆)

    CF487E Tourists(圆方树+树链剖分+multiset/可删堆) Luogu 给出一个带点权的无向图,两种操作: 1.修改某点点权. 2.询问x到y之间简单路径能走过的点的最小点权. 题解 ...

  9. 2019 icpc南昌全国邀请赛-网络选拔赛J题 树链剖分+离线询问

    链接:https://nanti.jisuanke.com/t/38229 题意: 给一棵树,多次查询,每次查询两点之间权值<=k的边个数 题解: 离线询问,树链剖分后bit维护有贡献的位置即可 ...

随机推荐

  1. LeetCode之数据流中第一个唯一的数字

    使用一个Map维护数字出现的次数,使用一个链表维护只出现一次的数,使用一个变量记录是否找到过终止数字. AC代码: public class Solution { /* * @param : a co ...

  2. redis笔记之两种持久化备份方式(RDB & AOF)

    Redis支持的两种持久化备份方式(RDB & AOF) redis支持两种持久化方式,一种是RDB,一种是AOF. RDB是根据指定的规则定时将内存中的数据备份到硬盘上,AOF是在每次执行命 ...

  3. 通过cordova将vue项目打包为webapp

    准备工作:需要之前配置好vue-cli脚架构,安装好cordova环境.下面开始对vue.js项目进行打包,打包环境为Android. 可以看下我的github:https://github.com/ ...

  4. PHP 5 MySQLi 函数总结

    连接数据库 mysqli_connect() 函数打开一个到 MySQL 服务器的新的连接. <?php $con=mysqli_connect("localhost",&q ...

  5. discuz各个目录与文件的作用说明

    discuz下面有很多文件夹以及文件,你们都知道他们是做什么的么?肯定不知道了吧.但是我们有经常遇到这些文件,譬如在后台文件校验操作都遇到某些文件被修改,这时候也需要知道这些文件是有什么作用的.今天就 ...

  6. 《深入理解Java虚拟机》笔记--第四章、虚拟机性能监控与故障处理工具

    主要学习并记录在命令行中操作服务器时使用的六大命令工具,可视化工具JConsole和VisualVM在开发过程中熟悉. 一.jps:虚拟机进程状况工具(JVM Process Status Tool) ...

  7. ireport报表,打印时,报表加载失败的解决方法

    1.报表加载失败图示 2.解决方法 原创作者:DSHORE 作者主页:http://www.cnblogs.com/dshore123/ 原文出自:http://www.cnblogs.com/dsh ...

  8. Python抓取微博评论(二)

    对于新浪微博评论的抓取,首篇做的时候有些考虑不周,然后现在改正了一些地方,因为有人问,抓取评论的时候“爬前50页的热评,或者最新评论里的前100页“,这样的数据看了看,好像每条微博的评论都只能抓取到前 ...

  9. python基础(6)---set、collections介绍

    1.set(集合) set和dict类似,也是一组key的集合,但不存储value.由于key不能重复,所以,在set中,没有重复的key. 集合和我们数学中集合的概念是一样的,也有交集.并集.差集. ...

  10. 洛谷P2097 资料分发1 题解

    题目传送门 这道题竟然是橙色的: 因为可以用并查集来做,当然您用dfs也可以,不过应该要加优化. 一开始就把读入的合并起来,最后逐个查找就好啦... #include<bits/stdc++.h ...