「CSA72」MST

题目大意:有一个大小为 \(n\) 的无向完全图,\(x, y\) 之间的边权值为 \(a[\min(x,y)][\max(x,y)]\) ,初始为0,进行 \(m\) 次修改,每次将一个矩形的权值加上 \(w\) ,求出最后这张完全图的最小生成树的边权和。\(n,m \leq 100000\)。

解题思路:用 Borůvka 求最小生成树,每一轮求出每一个点所在联通块向外连的一条边权最小的边,并用线段树+扫描线维护最小值以及最小值所在的联通块编号。为了找到不在同一个联通块内的边权最小的边,所以额外记一个次小值,并时刻保证次小值所在的联通块编号与最小值不是同一个,那么要连出去的最小的边一定在这两者之间,总复杂度 \(O(nlog^2n)\)。

code

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf ((ll)(1e16))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T & x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
} #define par pair<ll, ll>
#define fi first
#define se second const int N = 100005; struct chino{ int t, l, r, w; } q[N<<2];
int fa[N], n, m, tot, cnt; ll ans;
par tmp[N]; inline int ask(int x){ return x == fa[x] ? x : fa[x] = ask(fa[x]); }
struct Node{
int id[2]; ll val[2];
inline Node(){ val[0] = val[1] = inf, id[0] = id[1] = 0; }
inline Node operator + (const int &w){
Node res = *this;
return res.val[0] += w, res.val[1] += w, res;
}
inline Node operator + (const Node &A){
Node res, rhs;
res = (val[0] < A.val[0] ? *this : A);
rhs = (val[0] < A.val[0] ? A : *this);
for(int i = 0; i < 2; i++)
if(ask(rhs.id[i]) != ask(res.id[0]) && rhs.val[i] < res.val[1])
res.val[1] = rhs.val[i], res.id[1] = rhs.id[i];
return res;
}
};
namespace Seg{
#define lson (u << 1)
#define rson (u << 1 | 1)
#define mid (l + r >> 1)
Node mn[N<<2]; ll tag[N<<2];
inline void build(int u, int l, int r){
tag[u] = 0;
if(l == r){
mn[u].val[0] = 0, mn[u].val[1] = inf;
mn[u].id[0] = l, mn[u].id[1] = 0; return;
}
build(lson, l, mid), build(rson, mid + 1, r);
mn[u] = mn[lson] + mn[rson];
}
inline void pushdown(int u){
if(!tag[u]) return;
mn[lson] = mn[lson] + tag[u], mn[rson] = mn[rson] + tag[u];
tag[lson] += tag[u], tag[rson] += tag[u], tag[u] = 0;
}
inline void change(int u, int l, int r, int L, int R, ll w){
if(l >= L && r <= R) return (void) (mn[u] = mn[u] + w, tag[u] += w);
pushdown(u);
if(L <= mid) change(lson, l, mid, L, R, w);
if(mid < R) change(rson, mid + 1, r, L, R, w);
mn[u] = mn[lson] + mn[rson];
}
} inline void Bruasolve(){
Seg::build(1, 1, n);
for(register int i = 1; i <= n; i++) tmp[i].fi = inf, tmp[i].se = 0;
int p = 1;
for(register int i = 1; i <= n; i++){
while(p <= cnt && q[p].t == i)
Seg::change(1, 1, n, q[p].l, q[p].r, q[p].w), p++;
Node x = Seg::mn[1];
par now = (ask(x.id[0]) != ask(i)) ? make_pair(x.val[0], x.id[0]) : make_pair(x.val[1], x.id[1]);
if(now.fi < tmp[ask(i)].fi) tmp[ask(i)] = now;
}
for(register int i = 1; i <= n; i++) if(fa[i] == i){
if(ask(tmp[i].se) != i && tmp[i].se) tot++, ans += tmp[i].fi, fa[ask(tmp[i].se)] = i;
}
} inline bool cmp(const chino &A, const chino &B){ return A.t < B.t; } signed main(){
read(n), read(m);
for(int i = 1, X1, X2, Y1, Y2, w; i <= m; i++){
read(X1), read(X2), read(Y1), read(Y2), read(w);
q[++cnt] = ((chino){X1, Y1, Y2, w});
q[++cnt] = ((chino){X2 + 1, Y1, Y2, -w});
q[++cnt] = ((chino){Y1, X1, X2, w});
q[++cnt] = ((chino){Y2 + 1, X1, X2, -w});
}
sort(q + 1, q + cnt + 1, cmp);
for(int i = 1; i <= n; i++) fa[i] = i;
while(tot < n - 1) Bruasolve(); cout << ans << endl;
return 0;
}

「CSA72」MST的更多相关文章

  1. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  2. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  3. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  4. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  5. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  6. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

  7. 「2014-3-18」multi-pattern string match using aho-corasick

    我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...

  8. 「2014-3-17」C pointer again …

    记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...

  9. 「2014-3-13」Javascript Engine, Java VM, Python interpreter, PyPy – a glance

    提要: url anchor (ajax) => javascript engine (1~4 articles) => java VM vs. python interpreter =& ...

随机推荐

  1. html css 如何将表头固定

    position属性取值为fixed时,则元素的位置将不受滚动条的影响,而是直接依据窗口定位,这就是将表头固定的最直接方法,网上其他途径感觉都是在走弯路.但是与此同时必须解决两个问题.第一:表体将随之 ...

  2. LintCode 190: Next Permutation

    LintCode 190: Next Permutation 题目描述 给定一个若干整数的排列,给出按正数大小进行字典序从小到大排序后的下一个排列. 如果没有下一个排列,则输出字典序最小的序列. 样例 ...

  3. 【leetcode 简单】第二十二题 对称二叉树

    给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的. 1 / \ 2 2 / \ / \ 3 4 4 3 但是下面这个 [1,2,2,null,3,nul ...

  4. 【leetcode 简单】第三题 回文数

    判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: 输入: -121 输出: false 解释: 从左向 ...

  5. HDU 2094 产生冠军 (map容器)

    title: 产生冠军 杭电 2094 tags: [acm,stl] 题目链接 Problem Description 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛. 球赛的规则 ...

  6. tf.name_scope tf.variable_scope学习

    1. 首先看看比较简单的 tf.name_scope(‘scope_name’). tf.name_scope 主要结合 tf.Variable() 来使用,方便参数命名管理. ''' Signatu ...

  7. linux wc命令的作用。

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...

  8. PIL图片合成旋转缩放

    用PIL实现图片的旋转,缩放,合成 我们需要知道合成位置的中心点坐标,用中心点坐标,不使用左顶点的坐标是由于缩放过程容易计算. 假设A是局部透明的图片,我们希望把B放在A的底部,仅从A的透明部分显示B ...

  9. GitHub vs GitLab:它们有什么区别?

    查看原文GitLab vs. GitHub: How Are They Different? 两者都是基于web的Git repositories(仓库),拥有流水线型的web开发流程,它们为开发团队 ...

  10. Effective C++笔记(四):设计与声明

    参考:http://www.cnblogs.com/ronny/p/3747186.html 条款18:让接口容易被正确使用,不易被误用 1,好的接口很容易被正确使用,不容易被误用.你应该在你的所有接 ...