CF487E Tourists 【圆方树 + 树剖 + 堆】
题目链接
题解
圆方树 + 树剖 裸题
建好圆方树维护路径上最小值即可
方点的值为其儿子的最小值,这个用堆维护
为什么只维护儿子?因为这样修改点的时候就只需要修改其父亲的堆
这样充分利用了一对一的特性优化了复杂度
如此询问时如果\(lca\)为方点,再询问一下\(lca\)的父亲即可
复杂度\(O(qlog^2n)\)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
#include<vector>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define ls (u << 1)
#define rs (u << 1 | 1)
using namespace std;
const int maxn = 200005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int hh[maxn],nne = 1,h[maxn],ne = 1;
struct EDGE{int to,nxt;}ed[maxn << 1],e[maxn << 1];
inline void build(int u,int v){
e[++nne] = (EDGE){v,hh[u]}; hh[u] = nne;
e[++nne] = (EDGE){u,hh[v]}; hh[v] = nne;
}
inline void add(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
struct HEAP{
priority_queue<int,vector<int>,greater<int> > a,b;
void ck(){while (!b.empty() && a.top() == b.top()) a.pop(),b.pop();}
int size(){return a.size() - b.size();}
void ins(int x){a.push(x);}
void del(int x){b.push(x);}
int top(){ck(); return size() ? a.top() : INF;}
}H[maxn];
int n,m,q,N,w[maxn];
int dfn[maxn],low[maxn],st[maxn],Top,cnt;
void dfs(int u,int las){
dfn[u] = low[u] = ++cnt; st[++Top] = u;
for (int k = hh[u],to; k; k = e[k].nxt)
if (k != las){
if (!dfn[to = e[k].to]){
dfs(to,k ^ 1);
low[u] = min(low[u],low[to]);
if (low[to] >= dfn[u]){
add(++N,u);
do{add(N,st[Top]);} while (st[Top--] != to);
}
}
else low[u] = min(low[u],dfn[to]);
}
}
int siz[maxn],top[maxn],dep[maxn],fa[maxn],son[maxn],id[maxn],Hash[maxn],Cnt;
void dfs1(int u){
siz[u] = 1;
Redge(u) if ((to = ed[k].to) != fa[u]){
fa[to] = u; dep[to] = dep[u] + 1;
dfs1(to);
if (u > n) H[u - n].ins(w[to]);
siz[u] += siz[to];
if (!son[u] || siz[to] > siz[son[u]]) son[u] = to;
}
if (u > n) w[u] = H[u - n].top();
}
void dfs2(int u,int flag){
top[u] = flag ? top[fa[u]] : u;
id[u] = ++Cnt; Hash[Cnt] = u;
if (son[u]) dfs2(son[u],1);
Redge(u) if ((to = ed[k].to) != fa[u] && to != son[u])
dfs2(to,0);
}
int mn[maxn << 2];
inline void upd(int u){mn[u] = min(mn[ls],mn[rs]);}
void build(int u,int l,int r){
if (l == r){
mn[u] = w[Hash[l]];
return;
}
int mid = l + r >> 1;
build(ls,l,mid);
build(rs,mid + 1,r);
upd(u);
}
void modify(int u,int l,int r,int pos,int v){
if (l == r){mn[u] = v; return;}
int mid = l + r >> 1;
if (mid >= pos) modify(ls,l,mid,pos,v);
else modify(rs,mid + 1,r,pos,v);
upd(u);
}
int query(int u,int l,int r,int L,int R){
if (l >= L && r <= R) return mn[u];
int mid = l + r >> 1;
if (mid >= R) return query(ls,l,mid,L,R);
if (mid < L) return query(rs,mid + 1,r,L,R);
return min(query(ls,l,mid,L,R),query(rs,mid + 1,r,L,R));
}
int solve1(int u,int v){
int ans = INF;
while (top[u] != top[v]){
if (dep[top[u]] < dep[top[v]]) swap(u,v);
ans = min(ans,query(1,1,N,id[top[u]],id[u]));
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u,v);
ans = min(ans,query(1,1,N,id[u],id[v]));
if (u > n && fa[u]) ans = min(ans,w[fa[u]]);
return ans;
}
void solve2(int u,int v){
modify(1,1,N,id[u],v);
if (fa[u]){
H[fa[u] - n].del(w[u]),H[fa[u] - n].ins(v);
w[fa[u]] = H[fa[u] - n].top();
modify(1,1,N,id[fa[u]],w[fa[u]]);
}
w[u] = v;
}
int main(){
N = n = read(); m = read(); q = read();
for (int i = 1; i <= n; i++) w[i] = read();
for (int i = 1; i <= m; i++) build(read(),read());
dfs(1,0);
dfs1(1);
dfs2(1,0);
build(1,1,N);
char opt; int a,b;
while (q--){
opt = getchar(); while (opt != 'A' && opt != 'C') opt = getchar();
a = read(); b = read();
if (opt == 'A') printf("%d\n",solve1(a,b));
else solve2(a,b);
}
return 0;
}
CF487E Tourists 【圆方树 + 树剖 + 堆】的更多相关文章
- CF487E Tourists(圆方树+树链剖分+multiset/可删堆)
CF487E Tourists(圆方树+树链剖分+multiset/可删堆) Luogu 给出一个带点权的无向图,两种操作: 1.修改某点点权. 2.询问x到y之间简单路径能走过的点的最小点权. 题解 ...
- CF487E Tourists[圆方树+树剖(线段树套set)]
做这题的时候有点怂..基本已经想到正解了..结果感觉做法有点假,还是看了正解题解.. 首先提到简单路径上经过的点,就想到了一个关于点双的结论:两点间简单路径上所有可能经过的点的并等于路径上所有点所在点 ...
- CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)
QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...
- CF487E Tourists 圆方树、树链剖分
传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...
- uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
- 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...
- Tourists——圆方树
CF487E Tourists 一般图,带修求所有简单路径代价. 简单路径,不能经过同一个点两次,那么每个V-DCC出去就不能再回来了. 所以可以圆方树,然后方点维护一下V-DCC内的最小值. 那么, ...
- CF487E Tourists - Tarjan缩点 + 树剖 + multiset
Solution 先Tarjan求出点双联通分量 并缩点. 用$multiset$维护 点双内的最小点权. 容易发现, 点双内的最小点权必须包括与它相连的割边的点权. 所以我们必须想办法来维护. 所以 ...
- CF487E Tourists(圆方树+堆+链剖)
本题解并不提供圆方树讲解. 所以不会圆方树的出门右转问yyb 没有修改的话圆方树+链剖. 方点的权值为点双连通分量里的最小值. 然后修改的话圆点照修,每一个方点维护一个小根堆. 考虑到可能被菊花卡死. ...
- CF487E Tourists【圆方树+tarjan+multiset+树剖+线段树】
圆方树不仅能解决仙人掌问题(虽然我仙人掌问题也没用过圆方树都是瞎搞过去的),还可以解决一般图的问题 一般图问题在于缩完环不是一棵树,所以就缩点双(包括双向边) 每个方点存他所在点双内除根以外的点的最小 ...
随机推荐
- 一个web应用的诞生(12)--再探首页
就要面对本章的一个难点了,说是难点可能仅仅对于我来说,毕竟我是一个js渣,既然首页打算使用动态加载的形式,那么与后台交互的方式就要进行选择,目前比较流行的为RESTful的形式,关于RESTful的文 ...
- Java构造方法与析构方法实例剖析
Java构造方法 类有一个特殊的成员方法叫作构造方法,它的作用是创建对象并初始化成员变量.在创建对象时,会自动调用类的构造方法. 构造方法定义规则:Java 中的构造方法必须与该类具有相同的名字,并且 ...
- 深入理解C++中的Const,Mutable以及Volatile
我一直认为const表示一个常量,常量就是一个无法被修改的值,但是没有深入理解const的实现,甚至不知道mutable和volatile的存在,最近在书中看到了这一部分的知识,所以本文将详细解析这几 ...
- 「Leetcode」974. Subarray Sums Divisible by K(Java)
分析 这题场上前缀和都想出来了,然后就没有然后了...哭惹.jpg 前缀和相减能够得到任意一段连续区间的和,然后他们取余\(K\)看余数是否为0就能得到.这是朴素的遍历算法.那么反过来说,如果两个前缀 ...
- php oci8 小试
Oracle_db.class.php <?phpclass Oracle_db{ public $link; public function __construct(){ ...
- 《零基础学HTML5+CSS3(全彩版)》读书笔记
2019年1月31日星期四 1点 <零基础学HTML5+CSS3(全彩版)>开始全面学习 前提: 11月20日开始学Python,可能因为太累了,也可能遇到了瓶颈,进入了一个迷茫期,1月6 ...
- selenium 列表循环定位方法。
话不多说,直接上代码. 就是循环第一层,然后拼接,然后继续循环,继续屏接,任你多少层都不是问题. def c_select(self, values, text): """ ...
- TP框架代码学习 学习记录 3.2.3
文件:think.class.php PHP提供register_shutdown_function()这个函数,能够在脚本终止前回调注册的函数,也就是当 PHP 程序执行完成后执行的函数.regis ...
- Linux学习—导航文件系统
与windows相同,Linux操作系统也是以被称之为分层目录结构的方式来组织文件的.这意味着文件是以树形结构的目录中进行组织的,该树形结构目录可能包含文件和其他目录.文件系统的第一个目录叫做根目录, ...
- 跳蚤APP
1.项目描述 我们致力于制作一款服务于校内师生的物品转让平台,在此平台上的用户可以发布要转让或欲购买的物品信息. 2.创新与收益 Need(需求) 如今在市场上有许多的二手交易线上平台,它们的服务范围 ...