BZOJ 2001

很神仙的cdq分治

先放论文的链接   顾昱洲_浅谈一类分治算法

我们考虑分治询问,用$solve(l, r)$表示询问编号在$[l, r]$时的情况,那么当$l == r$的时候,直接把询问代入跑一个最小生成树就好了。

然而问题是怎么缩小每一层分治的规模,因为每一层都用$n$个点$m$条边来算稳$T$。

那么我们可以进行两个过程:

1、Reduction

  把与当前询问有关的边权设为$inf$跑最小生成树,那么此时不被连到最小生成树中的边一定是没什么用的,直接扔掉,这一步可以缩边。

2、Contraction

  把与当前询问有关的边权设为$-inf$跑最小生成树,那么不考虑边权为$-inf$的边连成的最小生成树的若干个连通块的边和点都是可以缩到一起的,这一步可以缩点。

这样子我们把这两个操作做完之后就可以做到把问题的规模缩减的与询问区间相关了。

时间复杂度$O(nlog^2n)$。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair <int, ll> pin; const int N = 2e4 + ;
const int M = 5e4 + ;
const int Lg = ;
const ll inf = 1LL << ; int n, m, qn, ufs[N], siz[N], pos[M], sum[Lg];
ll val[M], ans[M];
pin q[M]; struct Edge {
int u, v, id;
ll val; friend bool operator < (const Edge &x, const Edge &y) {
return x.val < y.val;
} } e[Lg][M], c[M], t[M]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline int find(int x) {
return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
} inline void merge(int x, int y) {
int fx = find(x), fy = find(y);
if(fx == fy) return;
if(siz[fx] < siz[fy]) ufs[fx] = fy, siz[fy] += siz[fx];
else ufs[fy] = fx, siz[fx] += siz[fy];
} inline void clear(int tot) {
for(int i = ; i <= tot; i++) {
ufs[t[i].u] = t[i].u;
ufs[t[i].v] = t[i].v;
siz[t[i].u] = siz[t[i].v] = ;
}
} inline void cont(int &tot, ll &nowVal) {
int cnt = ;
clear(tot);
sort(t + , t + + tot);
for(int i = ; i <= tot; i++) {
int u = find(t[i].u), v = find(t[i].v);
if(u == v) continue;
merge(u, v);
c[++cnt] = t[i];
} for(int i = ; i <= cnt; i++) {
ufs[c[i].u] = c[i].u;
ufs[c[i].v] = c[i].v;
siz[c[i].u] = siz[c[i].v] = ;
} for(int i = ; i <= cnt; i++) {
if(c[i].val == -inf) continue;
int u = find(c[i].u), v = find(c[i].v);
if(u == v) continue;
merge(u, v);
nowVal += c[i].val;
} cnt = ;
for(int i = ; i <= tot; i++) {
int u = find(t[i].u), v = find(t[i].v);
if(u == v) continue;
c[++cnt] = t[i];
pos[t[i].id] = cnt;
c[cnt].u = ufs[t[i].u];
c[cnt].v = ufs[t[i].v];
} for(int i = ; i <= cnt; i++) t[i] = c[i];
tot = cnt;
} void redu(int &tot) {
int cnt = ;
clear(tot);
sort(t + , t + + tot);
for(int i = ; i <= tot; i++) {
if(find(t[i].u) != find(t[i].v)) {
merge(t[i].u, t[i].v);
c[++cnt] = t[i];
pos[t[i].id] = cnt;
} else if(t[i].val == inf) {
c[++cnt] = t[i];
pos[t[i].id] = cnt;
}
} for(int i = ; i <= cnt; i++) t[i] = c[i];
tot = cnt;
} void solve(int l, int r, int now, ll nowVal) {
int tot = sum[now];
if(l == r) val[q[l].first] = q[l].second;
for(int i = ; i <= tot; i++)
e[now][i].val = val[e[now][i].id];
for(int i = ; i <= tot; i++)
t[i] = e[now][i], pos[e[now][i].id] = i; if(l == r) {
ans[l] = nowVal;
sort(t + , t + + tot);
clear(tot);
for(int i = ; i <= tot; i++) {
int u = find(t[i].u), v = find(t[i].v);
if(u == v) continue;
merge(u, v);
ans[l] += t[i].val;
}
return;
} for(int i = l; i <= r; i++)
t[pos[q[i].first]].val = -inf;
cont(tot, nowVal); for(int i = l; i <= r; i++)
t[pos[q[i].first]].val = inf;
redu(tot); ++now;
for(int i = ; i <= tot; i++)
e[now][i] = t[i];
sum[now] = tot; int mid = (l + r) / ;
solve(l, mid, now, nowVal);
solve(mid + , r, now, nowVal);
} int main() {
// freopen("1.in", "r", stdin); read(n), read(m), read(qn);
for(int i = ; i <= m; i++) {
read(e[][i].u), read(e[][i].v), read(e[][i].val);
e[][i].id = i;
val[i] = e[][i].val;
}
for(int i = ; i <= qn; i++)
read(q[i].first), read(q[i].second); sum[] = m;
solve(, qn, , 0LL); for(int i = ; i <= qn; i++)
printf("%lld\n", ans[i]); return ;
}

Luogu 3206 [HNOI2010]城市建设的更多相关文章

  1. [HNOI2010]城市建设

    [HNOI2010]城市建设 玄学cdq O(nlog^2n)的动态最小生成树 其实就是按照时间cdq分治+剪枝(剪掉一定出现和不可能出现的边) 处理[l,r]之间的修改以及修改之后的询问,不能确定是 ...

  2. 【BZOJ2001】[HNOI2010]城市建设(CDQ分治,线段树分治)

    [BZOJ2001][HNOI2010]城市建设(CDQ分治,线段树分治) 题面 BZOJ 洛谷 题解 好神仙啊这题.原来想做一直不会做(然而YCB神仙早就切了),今天来怒写一发. 很明显这个玩意换种 ...

  3. 【LG3206】[HNOI2010]城市建设

    [LG3206][HNOI2010]城市建设 题面 洛谷 题解 有一种又好想.码得又舒服的做法叫线段树分治+\(LCT\) 但是因为常数过大,无法跑过此题. 所以这里主要介绍另外一种玄学\(cdq\) ...

  4. BZOJ2001 HNOI2010 城市建设

    题目大意:动态最小生成树,可以离线,每次修改后回答,点数20000,边和修改都是50000. 顾昱洲是真的神:顾昱洲_浅谈一类分治算法 链接: https://pan.baidu.com/s/1c2l ...

  5. BZOJ2001 HNOI2010城市建设(线段树分治+LCT)

    一个很显然的思路是把边按时间段拆开线段树分治一下,用lct维护MST.理论上复杂度是O((M+Q)logNlogQ),实际常数爆炸T成狗.正解写不动了. #include<iostream> ...

  6. [HNOI2010] 城市建设_动态最小生成树(Dynamic_MST)

    这个题...暴力单次修改\(O(n)\),爆炸... $ $ 不过好在可以离线做 如果可以在 分治询问 的时候把图缩小的话就可以做了 硬着头皮把这个骚东西看完了 $ $ 动态最小生成树 然后,就把它当 ...

  7. 【CDQ分治】[HNOI2010]城市建设

    题目链接 线段树分治+LCT只有80 然后就有了CDQ分治的做法 把不可能在生成树里的扔到后面 把一定在生成树里的扔到并查集里存起来 分治到l=r,修改边权,跑个kruskal就行了 由于要支持撤销, ...

  8. 洛谷P3206 [HNOI2010]城市建设

    神仙题 题目大意: 有一张\(n\)个点\(m\)条边的无向联通图,每次修改一条边的边权,问每次修改之后这张图的最小生成树权值和 话说是不是\(cdq\)题目都可以用什么数据结构莽过去啊-- 这道题目 ...

  9. P3206 [HNOI2010]城市建设 [线段树分治+LCT维护动态MST]

    Problem 这题呢 就边权会在某一时刻变掉-众所周知LCT不支持删边的qwq- 所以考虑线段树分治- 直接码一发 如果 R+1 这个时间修改 那就当做 [L,R] 插入了一条边- 然后删的边和加的 ...

随机推荐

  1. 分布式使用Redis

    为什么我们做分布式使用Redis? https://www.cnblogs.com/yaodengyan/p/9717080.html 绝大部分写业务的程序员,在实际开发中使用 Redis 的时候,只 ...

  2. JVM年轻代(young generation)老年代(old generation tenured)持久代(permanent generation)GC

    关于jvm内存代,看到这篇文章,转发下 链接地址 ---多谢 虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent ...

  3. hibernate 一对一(One-to-One)

    一对一(one-to-one)实例(Person-IdCard) 一对一的关系在数据库中表示为主外关系.例如.人和身份证的关系.每个人都对应一个身份证号.我们应该两个表.一个是关于人信息的表(Pers ...

  4. hibernate 多对多(many-to-many)

    多对多(many-to-many):在操作和性能方面都不太理想,所以多对多的映射使用较少,实际使用中最好转换成一对多的对象模型:hibernate会为我们创建中间关联表,转换成两个一对多. 1. E- ...

  5. Protobuf-net 应用

    什么是ProtoBuf-net Protobuf是google开源的一个项目,是基于二进制的类似于XML,JSON这样的数据表示语言,用户数据序列化反序列化,google声称google的数据通信都是 ...

  6. CSS3的圆角border-radius属性

    一,语法解释 border-radius : none | <length>{1,4} [/ <length>{1,4} ] <length>: 由浮点数字和单位标 ...

  7. 《大教堂和集市》笔记——为什么一个本科生业余作品却成了全世界最流行的操作系统之一Linux?

    1. Eric Raymond有一篇著名文章<大教堂和集市>(The Cathedral and the Bazaar). 他说,世界上的建筑可以分两种:一种是集市,天天开放在那里,从无到 ...

  8. 致Oracle DBA 的一封信 (网上流传)

    1. 数据库的可用度,DBA 说了“不算”   --物化视图,加快查询速度 某些时候数据库的可用性,并不由DBA所设定.因为即使DBA对数据库有绝对掌控权,但用户可能从自己的工作和应用角度,与DBA的 ...

  9. PCIE接口的说明

    https://blog.csdn.net/u013253075/article/details/80835489

  10. jenkins使用HTML Publisher Plugin插件 拉取报告样式缺失问题解决

    ---------------------------------------------------------临时解决方案----亲测ok 要解决该问题,方式也比较简单,就是修改Content S ...