JZOJ 7377.欢乐豆
\(\text{Problem}\)
有一个有向完全图,所有的 \(u\) 到 \(v\) 的边权为 \(a_u\)
修改 \(m\) 此有向边边权,求最终图上两两点对的最短路之和
\(1\le n \le 10^5,1\le m \le 3000,1\le a_u \le 10^6\)
\(\text{Solution}\)
好题
如果没有修改边,那么 \(u\) 到任意一点的最短路为 \(a_u\)
有修改边,注意到 \(m\) 相对 \(n\) 很小,也就是说涉及的点很少,不妨称其为特殊点
显然特殊点个数最多为 \(O(m)\) 的,且特殊边也是 \(O(m)\) 的
考虑把特殊边连起来的点看成一个连通块(也就是视特殊边为无向边,把特殊点连起来)
我们导出这些特殊点构成的图,就是很多连通块的组成的图
这样再考虑两两点对间的最短路
无非分为特殊点到块内和到块外
\(1.\) 特殊点到块外就是特殊点到普通点和特殊点到不在此连通块内的特殊点
\(2.\) 特殊点到块内一定是特殊点到特殊点的最短路
先考虑 \(①\)
逐个考虑块内的点 \(x\) 到块外所有点的最短路
显然是此块内点 \(x\) 到此块内其它点 \(y\) 再到外面
即 \(dis(x,y)+a_y\) 的最小值
所以 \(①\) 贡献的最短路和为 \((n-cnt) \cdot min\)
再考虑 \(②\)
通过某种手段求出块内全源最短路,将这些 \(dis\) 加起来即可
有特殊边,有普通边,普通边是形如 \(a_u\) 的只和此端点有关
枚举起点,用线段树维护 \(dis\)
特殊边单点修改松弛,特殊边没被影响过的点用普通边松弛,这些点分散在多个区间,线段树上区间修改即可
然后就完成了,确实有点麻烦,但思路很清晰
\(\text{Code}\)
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#define ls (p << 1)
#define rs (ls | 1)
#define re register
using namespace std;
typedef long long LL;
const int N = 1e5 + 5;
const LL INF = 1e15;
int n, m, a[N], id[N], Q[N], cnt, tot, Tot, bz[N], h[N], H[N], color;
LL dis[N];
vector<int> d[N];
struct edge{int to, nxt, w;}e[N];
inline void add_edge(int x, int y, int z){e[++tot] = edge{y, h[x], z}, h[x] = tot;}
struct Edge{int to, nxt;}E[N];
inline void add_Edge(int x, int y){E[++Tot] = Edge{y, H[x]}, H[x] = Tot;}
struct node{int x; LL s;}b[N];
inline node Min(node a, node b){return (a.s <= b.s ? a : b);}
inline bool cmp(node a, node b){return a.s < b.s;}
inline void read(int &x)
{
x = 0; char ch = getchar(); int f = 1;
for(; !isdigit(ch); f = (ch == '-' ? -1 : f), ch = getchar());
for(; isdigit(ch); x = (x<<3) + (x<<1) + (ch^48), ch = getchar());
x *= f;
}
void dfs(int x)
{
bz[x] = color, Q[++cnt] = x;
for(re int i = H[x]; i; i = E[i].nxt) if (!bz[E[i].to]) dfs(E[i].to);
}
LL tag[N >> 1], Mn[N >> 1]; int Mp[N >> 1];
inline void pushup(int p)
{
if (Mn[ls] <= Mn[rs]) Mn[p] = Mn[ls], Mp[p] = Mp[ls];
else Mn[p] = Mn[rs], Mp[p] = Mp[rs];
}
void build(int p, int l, int r)
{
tag[p] = Mn[p] = INF;
if (l == r) return void(Mp[p] = l);
int mid = l + r >> 1;
build(ls, l, mid), build(rs, mid + 1, r), pushup(p);
}
inline void pushdown(int p)
{
if (tag[p] == INF) return;
if (Mn[ls] != INF + 1) Mn[ls] = min(Mn[ls], tag[p]), tag[ls] = min(tag[ls], tag[p]);
if (Mn[rs] != INF + 1) Mn[rs] = min(Mn[rs], tag[p]), tag[rs] = min(tag[rs], tag[p]);
tag[p] = INF;
}
void modify(int p, int l, int r, int tl, int tr, LL v)
{
if (tl > r || tr < l || v >= tag[p]) return;
if (tl <= l && r <= tr)
{
if (Mn[p] != INF + 1) Mn[p] = min(Mn[p], v), tag[p] = min(tag[p], v);
return;
}
pushdown(p);
int mid = l + r >> 1;
if (tl <= mid) modify(ls, l, mid, tl, tr, v);
if (tr > mid) modify(rs, mid + 1, r, tl, tr, v);
pushup(p);
}
void pushflag(int p, int l, int r, int x)
{
if (l == r) return void(Mn[p] = tag[p] = INF + 1);
pushdown(p);
int mid = l + r >> 1;
if (x <= mid) pushflag(ls, l, mid, x);
else pushflag(rs, mid + 1, r, x);
pushup(p);
}
void solve()
{
LL ans = 0, lst = 0;
for(re int i = 1; i <= n; i++)
if (!bz[i])
{
cnt = 0, ++color, dfs(i), sort(Q + 1, Q + cnt + 1);
int r = 1;
while (bz[b[r].x] == color && r <= n) ++r;
for(re int l = 1; l <= cnt; l++) id[Q[l]] = l;
for(re int l = 1; l <= cnt; l++)
{
build(1, 1, cnt), modify(1, 1, cnt, l, l, 0);
for(re int j = 1; j <= cnt; j++)
{
node now = node{Mp[1], Mn[1]};
for(re int k = h[Q[now.x]]; k; k = e[k].nxt) modify(1, 1, cnt, id[e[k].to], id[e[k].to], now.s + e[k].w);
if (d[Q[now.x]].size())
{
modify(1, 1, cnt, 1, id[d[Q[now.x]][0]] - 1, now.s + a[Q[now.x]]);
for(re int k = 1; k < d[Q[now.x]].size(); k++)
modify(1, 1, cnt, id[d[Q[now.x]][k - 1]] + 1, id[d[Q[now.x]][k]] - 1, now.s + a[Q[now.x]]);
modify(1, 1, cnt, id[d[Q[now.x]][d[Q[now.x]].size() - 1]] + 1, cnt, now.s + a[Q[now.x]]);
}
else modify(1, 1, cnt, 1, cnt, now.s + a[Q[now.x]]);
if (r <= n) modify(1, 1, cnt, 1, cnt, now.s + a[Q[now.x]] + b[r].s);
ans += (dis[now.x] = now.s), pushflag(1, 1, cnt, now.x);
}
LL mi = INF;
for(re int j = 1; j <= cnt; j++) mi = min(mi, dis[j] + a[Q[j]]);
ans += mi * (n - cnt);
}
}
printf("%lld\n", ans);
}
int main()
{
freopen("happybean.in", "r", stdin), freopen("happybean.out", "w", stdout);
read(n), read(m);
for(re int i = 1; i <= n; i++) read(a[i]), b[i].x = i, b[i].s = a[i]; sort(b + 1, b + n + 1, cmp);
for(re int i = 1, x, y, z; i <= m; i++)
read(x), read(y), read(z), add_edge(x, y, z), d[x].push_back(y), add_Edge(x, y), add_Edge(y, x);
for(re int i = 1; i <= n; i++) sort(d[i].begin(), d[i].end());
solve();
}
JZOJ 7377.欢乐豆的更多相关文章
- (jzoj snow的追寻)线段树维护树的直径
jzoj snow的追寻 DFS序上搞 合并暴力和,记录最长链和当前最远点,距离跑LCA # include <stdio.h> # include <stdlib.h> # ...
- [jzoj]3506.【NOIP2013模拟11.4A组】善良的精灵(fairy)(深度优先生成树)
Link https://jzoj.net/senior/#main/show/3506 Description 从前有一个善良的精灵. 一天,一个年轻人B找到她并请他预言他的未来.这个精灵透过他的水 ...
- [jzoj]3468.【NOIP2013模拟联考7】OSU!(osu)
Link https://jzoj.net/senior/#main/show/3468 Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: ...
- [jzoj]5478.【NOIP2017提高组正式赛】列队
Link https://jzoj.net/senior/#main/show/5478 Description Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校 ...
- [jzoj]1115.【HNOI2008】GT考试
Link https://jzoj.net/senior/#main/show/1115 Description 申准备报名参加GT考试,准考证号为n位数X1X2X3...Xn-1Xn(0<=X ...
- [jzoj]2538.【NOIP2009TG】Hankson 的趣味题
Link https://jzoj.net/senior/#main/show/2538 Description Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫H ...
- [jzoj]4216.【NOIP2015模拟9.12】平方和
Link https://jzoj.net/senior/#main/show/4216 Description 给出一个N个整数构成的序列,有M次操作,每次操作有一下三种: ①Insert Y X, ...
- [jzoj]2938.【NOIP2012模拟8.9】分割田地
Link https://jzoj.net/senior/#main/show/2938 Description 地主某君有一块由2×n个栅格组成的土地,有k个儿子,现在地主快要终老了,要把这些土地分 ...
- [jzoj]2505.【NOIP2011模拟7.29】藤原妹红
Link https://jzoj.net/senior/#main/show/2505 Description 在幻想乡,藤原妹红是拥有不老不死能力的人类.虽然不喜欢与人们交流,妹红仍然保护着误入迷 ...
- [jzoj]3875.【NOIP2014八校联考第4场第2试10.20】星球联盟(alliance)
Link https://jzoj.net/senior/#main/show/3875 Problem 在遥远的S星系中一共有N个星球,编号为1…N.其中的一些星球决定组成联盟,以方便相互间的交流. ...
随机推荐
- goioc:一个使用 Go 写的简易的 ioc 框架
目录 goioc 介绍 快速上手 接口介绍 使用 goioc 如何使用 生命周期 实例化 获取对象 结构体字段依赖注入 Dispose 接口 反射形式使用 goioc 如何使用 接口.结构体.结构体指 ...
- PHP8.1.10手动安装教程及报错解决梳理
安装教程参考一:https://www.cnblogs.com/haw2106/p/9839655.html 安装教程参考二:https://www.cnblogs.com/jiangfeilong/ ...
- 浏览器DevTools使用技巧
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:正则 作为一名前端开发人员,平时开发中使用最多的就是 Ch ...
- Springboot优雅进行字段检验
Springboot优雅进行字段检验 1.Controller VS Service 推荐与业务无关的放在controller层中进行校验,而与业务相关的放在service层中校验. 2.常用校验工具 ...
- Python数据类型+运算符
Python基础数据类型 上期练习讲解 # 练习一.想办法打印出jason l1 = [11, 22, 'kevin', ['tony', 'jerry', [123, 456, 'jason'] ] ...
- [奶奶看了都会]ChatGPT保姆级注册教程
大家好,我是小卷 最近几天OpenAI发布的ChatGPT聊天机器人火出天际了,连着上了各个平台的热搜榜.这个聊天机器人最大的特点是模仿人类说话风格同时回答大量问题. 有人说ChatGPT是真正的人工 ...
- angr_ctf——从0学习angr(二):状态操作和约束求解
状态操作 angr中提到的状态(state)实际上是一个Simstate类,该类可由Project预设得到.预设完成后,还可以根据需要对某些部分进行细化操作. 一个state包含了程序运行到某个阶段时 ...
- c++11 线程池--鸿蒙OS
一个你应该学习的线程池 说明 原理:线程+优先级队列.源码没有涉及STL,没有复杂高深的语法,安全性做得很好: queue的安全使用方式top和pop以及empty的判断都是使用了 std::lock ...
- salesforce零基础学习(一百二十三)Transaction Security 浅入浅出
本篇参考: https://help.salesforce.com/s/articleView?id=sf.enhanced_transaction_security_policy_types.htm ...
- PowerDotNet平台化软件架构设计与实现系列(14):平台建设指南
软件开发中常见的几种不同服务模型包括SaaS(软件即服务).LaaS(许可即服务).PaaS(平台即服务).CaaS(容器即服务).IaaS(基础设施即服务)和FaaS(功能即服务). 很多人认为Ia ...