uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
…
- 学习了一波圆方树
- 学习了一波点分治
- 学习了一波可删除堆(巧用 ? STL)
传送门: Icefox_zhx
注意看代码看怎么构建圆方树的.
tips:tips:tips:圆方树内存记得开两倍
CODE
#include <vector>
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
inline void read(int &num) {
char ch; int flg=1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
for(num=0; isdigit(ch); num=num*10+ch-'0',ch=getchar()); num*=flg;
}
const int MAXN = 100005;
const int INF = 1e9;
int n, m, q, tot, w[MAXN], dfn[MAXN<<1], tmr, stk[MAXN], indx;
vector<int> e[MAXN];
struct Heap {
priority_queue<int, vector<int>, greater<int> >A, B;
inline void insert(int x) { A.push(x); }
inline void erase(int x) { B.push(x); }
inline int top() {
while(!B.empty() && A.top() == B.top()) A.pop(), B.pop();
return A.empty() ? INF : A.top();
}
}W[MAXN];
int fir[MAXN<<1], to[MAXN<<2], nxt[MAXN<<2], cnt;
inline void add(int u, int v) {
to[cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt++;
}
int tarjan(int u, int fa) {
int lowu = dfn[u] = ++tmr;
stk[++indx] = u;
for(int v, lowv, i = 0, siz = e[u].size(); i < siz; ++i)
if(!dfn[v=e[u][i]]) {
lowu = min(lowu, lowv=tarjan(v, u));
if(lowv >= dfn[u]) {
fir[++tot] = -1;
do {
W[tot-n].insert(w[stk[indx]]), add(tot, stk[indx]);
}while(stk[indx--] != v);
add(u, tot);
}
}
else if(v != fa) lowu = min(lowu, dfn[v]);
return lowu;
}
int dep[MAXN<<1], fa[MAXN<<1], sz[MAXN<<1], top[MAXN<<1], son[MAXN<<1], seq[MAXN<<1];
void dfs(int u, int ff) {
dep[u] = dep[fa[u]=ff] + (sz[u]=1);
for(int v, i = fir[u]; ~i; i = nxt[i]) {
dfs(v=to[i], u), sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp; seq[dfn[u] = ++tmr] = u;
if(son[u]) dfs2(son[u], tp);
for(int v, i = fir[u]; ~i; i = nxt[i])
if((v=to[i]) != son[u]) dfs2(v, v);
}
int mn[MAXN<<3];
inline void upd(int i) { mn[i] = min(mn[i<<1], mn[i<<1|1]); }
void build(int i, int l, int r) {
if(l == r) { mn[i] = seq[l] <= n ? w[seq[l]] : W[seq[l]-n].top(); return; }
int mid = (l + r) >> 1;
build(i<<1, l, mid);
build(i<<1|1, mid+1, r);
upd(i);
}
void modify(int i, int l, int r, int x) {
if(l == r) { mn[i] = seq[l] <= n ? w[seq[l]] : W[seq[l]-n].top(); return; }
int mid = (l + r) >> 1;
if(x <= mid) modify(i<<1, l, mid, x);
else modify(i<<1|1, mid+1, r, x);
upd(i);
}
int query(int i, int l, int r, int x, int y) {
if(l == x && r == y) return mn[i];
int mid = (l + r) >> 1;
if(y <= mid) return query(i<<1, l, mid, x, y);
else if(x > mid) return query(i<<1|1, mid+1, r, x, y);
else return min(query(i<<1, l, mid, x, mid), query(i<<1|1, mid+1, r, mid+1, y));
}
inline int Min(int x, int y) {
int res = INF;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res = min(res, query(1, 1, tot, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if(dfn[x] < dfn[y]) swap(x, y);
res = min(res, query(1, 1, tot, dfn[y], dfn[x]));
if(y > n) res = min(res, w[fa[y]]);
return res;
}
int main() {
read(n), read(m), read(q); tot = n;
for(int i = 1; i <= n; ++i) fir[i] = -1, read(w[i]);
for(int i = 1, x, y; i <= m; ++i)
read(x), read(y), e[x].push_back(y), e[y].push_back(x);
tarjan(1, 0); tmr = 0; dfs(1, 0); dfs2(1, 1);
build(1, 1, tot);
char s; int x, y;
while(q--) {
while(!isalpha(s=getchar()));
read(x), read(y);
if(s == 'C') {
if(fa[x]) {
W[fa[x]-n].erase(w[x]);
W[fa[x]-n].insert(y);
modify(1, 1, tot, dfn[fa[x]]);
}
w[x] = y;
modify(1, 1, tot, dfn[x]);
}
else printf("%d\n", Min(x, y));
}
}
uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)的更多相关文章
- UOJ #30. [CF Round #278] Tourists
UOJ #30. [CF Round #278] Tourists 题目大意 : 有一张 \(n\) 个点, \(m\) 条边的无向图,每一个点有一个点权 \(a_i\) ,你需要支持两种操作,第一种 ...
- 圆方树简介(UOJ30:CF Round #278 Tourists)
我写这篇博客的原因 证明我也是学过圆方树的 顺便存存代码 前置技能 双联通分量:点双 然后就没辣 圆方树 建立 新建一个图 定义原图中的所有点为圆点 对于每个点双联通分量(只有两个点的也算) 建立一个 ...
- [CF Round #278] Tourists
给定一个n个点m条边的无向图,求图上的两点的所有的简单路径之间的最小边. 蓝链 $ n,m,q \leq 100000, w_i \leq 10 ^7$ Solution 考虑建立用缩点双来建立广义圆 ...
- CF487E Tourists(圆方树+树链剖分+multiset/可删堆)
CF487E Tourists(圆方树+树链剖分+multiset/可删堆) Luogu 给出一个带点权的无向图,两种操作: 1.修改某点点权. 2.询问x到y之间简单路径能走过的点的最小点权. 题解 ...
- CF487E Tourists 圆方树、树链剖分
传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...
- Tourists——圆方树
CF487E Tourists 一般图,带修求所有简单路径代价. 简单路径,不能经过同一个点两次,那么每个V-DCC出去就不能再回来了. 所以可以圆方树,然后方点维护一下V-DCC内的最小值. 那么, ...
- UOJ #30. 【CF Round #278】Tourists
Description Cyberland 有 n 座城市,编号从 1 到 n,有 m 条双向道路连接这些城市.第 j 条路连接城市 aj 和 bj.每天,都有成千上万的游客来到 Cyberland ...
- UOJ #30【CF Round #278】Tourists
求从$ x$走到$ y$的路径上可能经过的最小点权,带修改 UOJ #30 $ Solution:$ 如果两个点经过了某个连通分量,一定可以走到这个连通分量的最小值 直接构建圆方树,圆点存原点的点权 ...
- 【题解】【CF Round #278】Tourists
圆方树第二题…… 图中询问的是指定两点之间简单路径上点的最小权值.若我们建出圆方树,圆点的权值为自身权值,方点的权值为所连接的圆点的权值最小值(即点双连通分量中的最小权值).我们可以发现其实就是这两点 ...
随机推荐
- poj1155 TELE (树上分组背包)
题目链接:https://vjudge.net/problem/POJ-1155 题意:给定一颗以1为根的边权树,有n个结点,其中m个叶子结点,每个叶子结点有一个价值.要求从m个叶子结点中选最多的结点 ...
- 什么是分析型数据库PostgreSQL版
分析型数据库PostgreSQL版(原HybridDB for PostgreSQL)为您提供简单.快速.经济高效的 PB 级云端数据仓库解决方案.分析型数据库PostgreSQL版 兼容 Green ...
- FileSystemResource 找不到文件
环境 Spring 3.2.5.RELEASE 原因 使用 FileSystemResource 加载文件的过程中,发现一个奇怪的现象,路径完全正确,但是找不到文件的情况.可能的原因是文件的路径上有压 ...
- Java实现链队
一.分析 队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素.允许插入的一端称为队尾,允许删除的一端称为队头. 链队是指采用链式存储结构实现的队列,它的基本操作如下: 1.初始 ...
- ale.js 对比其他框架
欢迎!我们相信你来这里的目的就是为了解 Ale 与其他大型框架的区别,这也正是我们想要在此回答的. 客观来说,作为 Ale 的核心开发者,我们肯定会更偏爱 Ale,认为对于某些问题来讲用 Ale 解决 ...
- X86逆向5:破解程序的自效验
在软件的破解过程中,经常会遇到程序的自效验问题,什么是自效验?当文件大小发生变化,或者MD5特征变化的时候就会触发自效验暗装,有些暗装是直接退出,而有些则是格盘蓝屏等,所以在调试这样的程序的时候尽量在 ...
- 【sublime Text】关闭sublime的更新提醒和激活提醒
下载了原版的sublime Text,未激活的,每次启动都会提醒要去更新么?需要激活吧 ? 超级烦.[谁让没有激活呢?] 那没办法 ,激活吧! Help ---- Enter License--> ...
- springboot指定redis库编号配置实现
yml配置 spring: redis: database: #shiro host: 127.0.0.1 port: timeout: password: null redis-cache: dat ...
- Java程序员转行大数据的优势
大数据时代,中国IT环境也将面临重新洗牌,不仅仅是企业,更是程序员们转型可遇而不可求的机遇. 国内大多数大型互联网公司的程序员被称作研发工程师,但实际上国内几乎没有研发项目,只能叫做开发.开发程序员的 ...
- VS2019 快捷键
工欲善其事,必先利其器,整理了下VS最常用的快捷键,查看了不少资料,汇总了下,没有的自己补充,可以打印,用Excel编辑的. 可编辑版本下载:Excel文件下载 你可能需要查询其他的快捷键,MSDN介 ...