UOJ #30. [CF Round #278] Tourists

题目大意 :

有一张 \(n\) 个点, \(m\) 条边的无向图,每一个点有一个点权 \(a_i\) ,你需要支持两种操作,第一种操作修改一个点的点权,第二种操作给出 \(u, v\),求一个点 \(x\) ,存在一条 \(u-x-v\) 不经过重复点的路径且 \(a_x\) 最小

\(1 \leq n,m \leq 10^5\)

解题思路 :

​ 考虑如果 \(u-x\) 和 \(x-v\) 经过了同一个割点,那么一定不合法,也就是说 \(x\) 一定在 \(u-v\) 之间的点双联通分量里。于是将圆方树建出来,对于每一个方点用一个 \(\text{multiset}\) 维护最小值,树链剖分维护路径答案,注意特判 \(lca\) 是方点的情况

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#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 f = 0, ch = 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 lson (u << 1)
#define rson (u << 1 | 1) const int N = 1000005;
char str[20];
vector<int> g[N];
int ass[N], n, m, q; struct SegmentTree{
int s[N<<2];
inline SegmentTree(){ memset(s, 127, sizeof(s)); }
inline void modify(int u, int l, int r, int pos, int x){
if(l == r) return (void) (s[u] = x);
int mid = l + r >> 1;
if(pos <= mid) modify(lson, l, mid, pos, x);
else modify(rson, mid + 1, r, pos, x);
s[u] = min(s[lson], s[rson]);
}
inline int query(int u, int l, int r, int L, int R){
if(l >= L && r <= R) return s[u];
int mid = l + r >> 1, res = inf;
if(L <= mid) res = min(query(lson, l, mid, L, R), res);
if(mid < R) res = min(query(rson, mid + 1, r, L, R), res);
return res;
}
}Seg;
namespace Gao{
multiset<int> st[N];
vector<int> g[N];
int dep[N], sz[N], ff[N], ms[N], dfn[N], top[N], cnt;
inline void dfs(int u, int fa){
dep[u] = dep[fa] + 1, sz[u] = 1, ff[u] = fa;
if(fa > n) st[fa].insert(ass[u]);
for(int i = 0; i < g[u].size(); i++){
int v = g[u][i];
if(v == fa) continue;
dfs(v, u), sz[u] += sz[v];
if(sz[v] > sz[ms[u]]) ms[u] = v;
}
}
inline void split(int u, int chain, int fa){
dfn[u] = ++cnt, top[u] = chain;
int tmp = u <= n ? ass[u] : (*st[u].begin());
Seg.modify(1, 1, 2 * n, dfn[u], tmp);
if(ms[u]) split(ms[u], chain, u);
for(int i = 0; i < g[u].size(); i++){
int v = g[u][i];
if(v == fa || v == ms[u]) continue;
split(v, v, u);
}
}
inline int query(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, Seg.query(1, 1, 2 * n, dfn[top[x]], dfn[x]));
x = ff[top[x]];
}
if(dfn[x] > dfn[y]) swap(x, y);
res = min(res, Seg.query(1, 1, 2 * n, dfn[x], dfn[y]));
if(ff[x] <= n && ff[x]) res = Min(res, ass[ff[x]]);
return res;
}
inline void modify(int x, int y){
Seg.modify(1, 1, 2 * n, dfn[x], y);
if(x > 1){
st[ff[x]].erase(st[ff[x]].find(ass[x]));
st[ff[x]].insert(y);
Seg.modify(1, 1, 2 * n, dfn[ff[x]], *(st[ff[x]].begin()));
}
ass[x] = y;
}
}
namespace Graph{
int a[N], nxt[N], head[N], dfn[N], low[N], st[N], top, Index, id, cnt = 1;
inline void add(int x, int y){
a[++cnt] = y, nxt[cnt] = head[x], head[x] = cnt;
}
inline void tarjan(int u, int fa){
dfn[u] = low[u] = ++Index;
for(int p = head[u]; p; p = nxt[p]){
if((p ^ 1) == fa) continue;
int v = a[p];
if(dfn[v]){ low[u] = min(low[u], dfn[v]); continue; }
st[++top] = v, tarjan(v, p);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]){
id++;
for(; st[top] != v; top--){
Gao::g[id].push_back(st[top]);
Gao::g[st[top]].push_back(id);
}
top--;
Gao::g[id].push_back(v), Gao::g[v].push_back(id);
Gao::g[id].push_back(u), Gao::g[u].push_back(id);
}
}
}
inline void Build(){
id = n;
for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i, 0);
}
}
signed main(){
read(n), read(m), read(q);
for(int i = 1; i <= n; i++) read(ass[i]);
for(int i = 1, x, y; i <= m; i++){
read(x), read(y);
Graph::add(x, y), Graph::add(y, x);
}
Graph::Build();
Gao::dfs(1, 0), Gao::split(1, 1, 0);
for(int i = 1, x, y; i <= q; i++){
scanf("%s", str); read(x), read(y);
if(str[0] == 'C') Gao::modify(x, y);
if(str[0] == 'A') printf("%d\n", Gao::query(x, y));
}
return 0;
}

UOJ #30. [CF Round #278] Tourists的更多相关文章

  1. 圆方树简介(UOJ30:CF Round #278 Tourists)

    我写这篇博客的原因 证明我也是学过圆方树的 顺便存存代码 前置技能 双联通分量:点双 然后就没辣 圆方树 建立 新建一个图 定义原图中的所有点为圆点 对于每个点双联通分量(只有两个点的也算) 建立一个 ...

  2. [CF Round #278] Tourists

    给定一个n个点m条边的无向图,求图上的两点的所有的简单路径之间的最小边. 蓝链 $ n,m,q \leq 100000, w_i \leq 10 ^7$ Solution 考虑建立用缩点双来建立广义圆 ...

  3. UOJ #30【CF Round #278】Tourists

    求从$ x$走到$ y$的路径上可能经过的最小点权,带修改  UOJ #30 $ Solution:$ 如果两个点经过了某个连通分量,一定可以走到这个连通分量的最小值 直接构建圆方树,圆点存原点的点权 ...

  4. UOJ #30. 【CF Round #278】Tourists

    Description Cyberland 有 n 座城市,编号从 1 到 n,有 m 条双向道路连接这些城市.第 j 条路连接城市 aj 和 bj.每天,都有成千上万的游客来到 Cyberland ...

  5. UOJ30——【CF Round #278】Tourists

    1.感谢taorunz老师 2.题目大意:就是给个带权无向图,然后有两种操作, 1是修改某个点的权值 2是询问,询问一个值,就是u到v之间经过点权的最小值(不可以经过重复的点) 操作数,点数,边数都不 ...

  6. 【题解】【CF Round #278】Tourists

    圆方树第二题…… 图中询问的是指定两点之间简单路径上点的最小权值.若我们建出圆方树,圆点的权值为自身权值,方点的权值为所连接的圆点的权值最小值(即点双连通分量中的最小权值).我们可以发现其实就是这两点 ...

  7. uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)

    - 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...

  8. 【Codefoces487E/UOJ#30】Tourists Tarjan 点双连通分量 + 树链剖分

    E. Tourists time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard inpu ...

  9. [UOJ30/Codeforces Round #278 E]Tourists

    传送门 好毒瘤的一道题QAQ,搞了好几好几天. UOJ上卡在了53个点,CF上过了,懒得优化常数了 刚看时一眼Tarjan搞个强连通分量然后缩点树链剖分xjb搞搞就行了,然后写完了,然后WA了QAQ. ...

随机推荐

  1. 【CodeForces】626 F. Group Projects 动态规划

    [题目]F. Group Projects [题意]给定k和n个数字ai,要求分成若干集合使得每个集合内部极差的总和不超过k的方案数.n<=200,m<=1000,1<=ai< ...

  2. Spring Boot中使用Spring Security进行安全控制

    我们在编写Web应用时,经常需要对页面做一些安全控制,比如:对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache ...

  3. 【leetcode 简单】 第七题 合并两个有序链表

    将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1->2- ...

  4. L - SOS Gym - 101775L 博弈

    题目链接:https://cn.vjudge.net/contest/274151#problem/L 题目大意:给你一个1*n的方格,两个人轮流放字母,每一次可以放"S"或者&q ...

  5. Thinkphp的SQL查询方式

    一.普通查询方式 a.字符串$arr=$m->where("sex=0 and username='gege'")->find();b.数组$data['sex']=0 ...

  6. 69.Spartan-6的SelectIO资源

    2.1.6 SelectIO资源 Spartan-6有丰富的I/O资源,包括SelectIO和RocketIO. Spartan-6每个I/O片(Tile)包含两个IOB.两个ILOGIC2.两个OL ...

  7. Linux实用命令之git-svn

    近日发现了有一个工具,git-svn,可以打通git svn之间的鸿沟. 很适合习惯于git,却需要维护svn代码的同学. 安装 sudo apt-get install git-svn 具体使用就不 ...

  8. Android快速入门(转自 农民伯伯: http://www.cnblogs.com/over140/)

    前言 这是前段时间用于公司Android入门培训的资料,学习Android三周时间收集整理的,时间仓促,希望能对像我这样还没入门就直接上项目的人一点帮助  :) 声明 欢迎转载,但请保留文章原始出处: ...

  9. 微信JS-SDK接口 + FLASK实现图片上传

    最近在做一个项目从全球各地采集图片,考虑采用微信JS-SDK来简化开发.图片会首先上传到微信的服务器,返回一个id,然后根据这个id去微信服务器获取图片.微信提供可选择的压缩图片功能.图片首先上传到微 ...

  10. Effective STL 阅读笔记: Item 3: Make copying cheap and correct for objects in containers

    容器 (Containers) 用来存储对象 (Objects), 但是被存储的对象却并非原原本本是你给他的那一个, 而是你指定对象的一个拷贝.而后续对该容器内存储对象的操作,大多也是基于拷贝的. 拷 ...