luoguP4115 QTREE4 链分治
具体看$qzc$论文吧......陈年老物了......
主要注意每个链头一棵线段树而不是一棵全局线段树
修改操作写完就是正确的,反而是初始化调了好一会......
跑的还是很快的,有些地方没优化常数也还可以接受
在$luogu$上把$Toptree$给卡下去了,现居$rank1$......
代码的话....借鉴一下思想就行了
实现就没有必要有些地方做得一样了
#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 sid 100050
#define eid 200050
#define ri register int
const int inf = 1e9; struct heap {
priority_queue <int> f, g;
inline void ins(int v) { if(v != -inf) f.push(v); }
inline void era(int v) { if(v != -inf) g.push(v); }
inline int top() {
while() {
if(f.empty()) return -inf;
if(g.empty()) return f.top();
if(f.top() == g.top()) f.pop(), g.pop();
else return f.top();
}
}
} h[sid], ans; int n, m, wn, cnp;
int cap[sid], nxt[eid], node[eid], fee[eid];
inline void addeg(int u, int v, int w) {
nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v; fee[cnp] = w;
nxt[++ cnp] = cap[v]; cap[v] = cnp; node[cnp] = u; fee[cnp] = w;
} #define cur node[i]
int sz[sid], pre[sid], fa[sid], dep[sid];
inline void dfs(int o) {
sz[o] = ;
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa[o]) {
fa[cur] = o; dep[cur] = dep[o] + fee[i]; dfs(cur);
sz[o] += sz[cur]; if(sz[cur] > sz[pre[o]]) pre[o] = cur;
}
} int id, onp, col[sid];
int anc[sid], len[sid], dfn[sid], ord[sid];
inline void dfs(int o, int tp) {
dfn[o] = ++ id; anc[o] = tp; ord[id] = o; len[tp] ++;
if(!pre[o]) return; dfs(pre[o], tp);
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa[o] && cur != pre[o]) dfs(cur, cur);
} int tnp, rt[sid];
struct seg { int l, r, v, ls, rs; } t[sid * ]; #define dis(x) dep[ord[x]]
inline void upd(int o, int l, int r) {
int ls = t[o].ls, rs = t[o].rs, mid = (l + r) >> ;
t[o].l = max(t[ls].l, t[rs].l + dis(mid + ) - dis(l));
t[o].r = max(t[rs].r, t[ls].r + dis(r) - dis(mid));
t[o].v = max(max(t[ls].v, t[rs].v), t[ls].r + t[rs].l + dis(mid + ) - dis(mid));
} inline void build(int &o, int l, int r) {
if(!o) o = ++ onp;
if(l == r) {
int x = ord[l];
for(ri i = cap[x]; i; i = nxt[i])
if(cur != fa[x] && cur != pre[x]) h[x].ins(t[rt[cur]].l + dep[cur] - dep[x]);
int d1 = h[x].top(); h[x].era(d1); int d2 = h[x].top(); h[x].ins(d1);
t[o].l = t[o].r = max(d1, ); t[o].v = max(, max(d1, d1 + d2));
return;
}
int mid = (l + r) >> ;
build(t[o].ls, l, mid);
build(t[o].rs, mid + , r);
upd(o, l, r);
} inline void mdf(int o, int l, int r, int v, int s) {
if(l == r) {
if(v == s) {
int d1 = h[v].top(); h[v].era(d1); int d2 = h[v].top(); h[v].ins(d1);
if(col[v]) t[o].l = t[o].r = d1, t[o].v = d1 + d2;
else t[o].l = t[o].r = max(d1, ), t[o].v = max(, max(d1, d1 + d2));
}
else {
h[v].ins(t[rt[s]].l + dep[s] - dep[v]);
int d1 = h[v].top(); h[v].era(d1); int d2 = h[v].top(); h[v].ins(d1);
if(col[v]) t[o].l = t[o].r = d1, t[o].v = d1 + d2;
else t[o].l = t[o].r = max(d1, ), t[o].v = max(, max(d1, d1 + d2));
}
return;
}
int mid = (l + r) >> ;
if(dfn[v] <= mid) mdf(t[o].ls, l, mid, v, s);
else mdf(t[o].rs, mid + , r, v, s);
upd(o, l, r);
} int main() {
wn = n = read();
for(ri i = ; i < n; i ++) {
int u = read(), v = read();
int w = read(); addeg(u, v, w);
}
dfs(); dfs(, ); ans.ins();
for(ri i = n; i; i --) {
int o = ord[i]; if(o != anc[o]) continue;
build(rt[o], dfn[o], dfn[o] + len[o] - );
ans.ins(t[rt[o]].v);
}
m = read(); char opt = ;
for(ri i = ; i <= m; i ++) {
opt = gc();
while(opt != 'C' && opt != 'A') opt = gc();
if(opt == 'C') {
int x = read(); col[x] ^= ;
if(col[x] == ) wn ++; else wn --;
for(ri o = x, p = o; o; o = fa[o]) {
int f = anc[o];
int p1 = t[rt[f]].v, d1 = t[rt[f]].l;
if(fa[f]) h[fa[f]].era(t[rt[f]].l + dep[f] - dep[fa[f]]);
mdf(rt[f], dfn[f], dfn[f] + len[f] - , o, p);
int p2 = t[rt[f]].v, d2 = t[rt[f]].l;
if(p1 != p2) ans.era(p1), ans.ins(p2);
p = o = f;
}
}
else {
if(wn == ) printf("They have disappeared.\n");
else printf("%d\n", ans.top());
}
}
return ;
}
luoguP4115 QTREE4 链分治的更多相关文章
- 洛谷 4115 Qtree4——链分治
题目:https://www.luogu.org/problemnew/show/P4115 论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb ...
- bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治
这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...
- [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)
题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...
- 2019.02.17 spoj Query on a tree VII(链分治)
传送门 跟QTREE6QTREE6QTREE6神似,改成了求连通块里的最大值. 于是我们对每条链开一个heapheapheap维护一下即可. MDMDMD终于1A1A1A链分治了. 代码: #incl ...
- 2019.02.17 spoj Query on a tree VI(链分治)
传送门 题意简述:给你一棵nnn个黑白点的树,支持改一个点的颜色,询问跟某个点颜色相同的连通块大小. 思路: 还是链分治 233 记fi,0/1f_{i,0/1}fi,0/1表示iii的所有颜色为0 ...
- 2019.02.17 spoj Query on a tree V(链分治)
传送门 题意简述: 给你一棵nnn个黑白点的树,初始全是黑点. 现在支持给一个点换颜色或者求整颗树中离某个点最近的白点跟这个点的距离. 思路: 考虑链分治维护答案,每个链顶用一个堆来维护答案,然后对于 ...
- 2019.02.16 spoj Query on a tree IV(链分治)
传送门 题意简述: 捉迷藏强化版(带有边权,可以为负数) 思路:好吧这次我们不用点分树,我们用听起来更屌的链分治. 直接把树剖成若干条重链,这样保证从任意一个点跳到根节点是不会跳超过logloglog ...
- 2019.02.16 bzoj5466: [Noip2018]保卫王国(链分治+ddp)
传送门 题意简述: mmm次询问,每次规定两个点必须选或者不选,求树上的带权最小覆盖. 思路: 考虑链分治+ddpddpddp 仍然是熟悉的套路,先考虑没有修改的状态和转移: 令fi,0/1f_{i, ...
- 2019.02.15 bzoj5210: 最大连通子块和(链分治+ddp)
传送门 题意:支持单点修改,维护子树里的最大连通子块和. 思路: 扯皮: bzojbzojbzoj卡常差评. 网上的题解大多用了跟什么最大子段和一样的转移方法. 但是我们实际上是可以用矩阵转移的传统d ...
随机推荐
- 【BZOJ】1023: [SHOI2008]cactus仙人掌图 静态仙人掌(DFS树)
[题意]给定仙人掌图(每条边至多在一个简单环上),求直径(最长的点对最短路径).n<=50000,m<=10^7. [算法]DFS树处理仙人掌 [题解]参考:仙人掌相关问题的处理方法(未完 ...
- BERT(Bidirectional Encoder Representations from Transformers)理解
BERT的新语言表示模型,它代表Transformer的双向编码器表示.与最近的其他语言表示模型不同,BERT旨在通过联合调节所有层中的上下文来预先训练深度双向表示.因此,预训练的BERT表示可以通过 ...
- Linux实用命令之git-svn
近日发现了有一个工具,git-svn,可以打通git svn之间的鸿沟. 很适合习惯于git,却需要维护svn代码的同学. 安装 sudo apt-get install git-svn 具体使用就不 ...
- linux下C语言实现多线程通信—环形缓冲区,可用于生产者(producer)/消费者(consumer)【转】
转自:http://blog.chinaunix.net/uid-28458801-id-4262445.html 操作系统:ubuntu10.04 前言: 在嵌入式开发中,只要是带操作系统的 ...
- SQLite3 安装、基本操作
1. 安装SQLite3 sudo apt-get install sqlite3 2. 安装Sqlite3编译需要的工具包 如果,你需要的话可以安装该工具包.只是为了体验一把,可以不安装.该项是可选 ...
- 千字短文解决工程师们关于SPI的迷糊!
串行外设接口 (SPI) 总线是一个工作在全双工模式下的同步串行数据链路.它可用于在单个主控制器和一个或多个从设备之间交换数据.其简单的实施方案只使用四条支持数据与控制的信号线(图 1): 图1:基本 ...
- linux常用命令一些解释
ls 命令是linux下最常用的命令.ls命令就是list的缩写缺省下ls用来打印出当前目录的清单如果ls指定其他目录那么就会显示指定目录里的文 件及文件夹清单. 通过ls 命令不仅可以查看li ...
- coding.net--多人合作开发git的使用
// 从conding拉下新项目 mkdir test cd test git clone https // 安装cocoapods gem sources --remove https://ruby ...
- 简单优化:Zipalign
Android SDK中包含一个“zipalign”的工具,它能够对打包的应用程序进行优化.在你的应用程序上运行zipalign,使得在运行时Android与应用程序间的交互更加有效率.因此,这种方式 ...
- 使用Opencv时编译错误
1)无法打开包括文件: “cv.h”: No such file or directory 我的配置文件没有问题,但是一直报错,我是在HEVC测试软件HM中调用了opencv. HM有很多个工程,我只 ...