Description

题库链接

给你张 \(n\) 个点 \(m\) 条边的连通无向图。 \(q\) 次操作,让你支持:

  1. 询问可以出现在两点之间的简单路路径上的点的最小权值;
  2. 修改某个点的点权。

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

Solution

显然在路径上如果存在一个点双,那么这个点双上的点是都能被经过的。

显然我们可以构建圆方树,方点维护点双中所有的点的点权,用堆实现。

值得注意的是,由于可能一个圆点周围有许多方点,如果更新时在每个方点内都更新的话,复杂度还是不正确的。所以我们规定每个方点只管辖其儿子的圆点。在求 \(lca\) 处特判一下即可。

Code

//It is made by Awson on 2018.3.17
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 1e5, INF = ~0u>>1;
void read(int &x) {char ch; bool flag = 0;for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }int X, n, m, q, u, v, a[(N<<1)+5]; char ch[3];
struct Edge {int u, v; };
struct Heap {priority_queue<int, vector<int>, greater<int> >p, q;void erase(int o) {q.push(o); }void push(int o) {p.push(o); }int top() {while (!q.empty() && p.top() == q.top()) p.pop(), q.pop(); return p.top(); }
}Q[(N<<1)+5];
stack<Edge>S;
int dfn[N+5], low[N+5], sccno[N+5], times, sccnum, pos;
int fa[(N<<1)+5], size[(N<<1)+5], dep[(N<<1)+5], top[(N<<1)+5], son[(N<<1)+5], idx[(N<<1)+5], b[(N<<1)+5];
struct graph {struct tt {int to, next; }edge[(N<<2)+5];int path[(N<<1)+5], top;void add(int u, int v) {edge[++top].to = v, edge[top].next = path[u], path[u] = top; }
}g1, g2;
struct Segment_tree {
#define lr(o) (o<<1)
#define rr(o) (o<<1|1)int sgm[(N<<3)+5];void build (int o, int l, int r) {if (l == r) {sgm[o] = a[b[l]]; return; } int mid = (l+r)>>1;build(lr(o), l, mid), build(rr(o), mid+1, r);sgm[o] = Min(sgm[lr(o)], sgm[rr(o)]);}int query(int o, int l, int r, int a, int b) {if (a <= l && r <= b) return sgm[o]; int mid = (l+r)>>1;int c1 = INF, c2 = INF;if (a <= mid) c1 = query(lr(o), l, mid, a, b);if (b > mid) c2 = query(rr(o), mid+1, r, a, b);return Min(c1, c2);}void insert(int o, int l, int r, int loc) {if (l == r) {sgm[o] = a[b[l]]; return; } int mid = (l+r)>>1;if (loc <= mid) insert(lr(o), l, mid, loc); else insert(rr(o), mid+1, r, loc);sgm[o] = Min(sgm[lr(o)], sgm[rr(o)]);}
}T;void tarjan(int o, int fa) {dfn[o] = low[o] = ++times;for (int i = g1.path[o]; i; i = g1.edge[i].next) {int v = g1.edge[i].to;if (!dfn[v]) {S.push((Edge){o, v});tarjan(v, o); low[o] = Min(low[o], low[v]);if (low[v] >= dfn[o]) {++n; ++sccnum;while (true) {Edge e = S.top(); S.pop();if (sccno[e.u] != sccnum) sccno[e.u] = sccnum, g2.add(n, e.u), g2.add(e.u, n);if (sccno[e.v] != sccnum) sccno[e.v] = sccnum, g2.add(n, e.v), g2.add(e.v, n);if (e.u == o && e.v == v) break;                    }}}else if (v != fa) low[o] = Min(low[o], dfn[v]);}
}
void dfs1(int o, int depth, int father) {fa[o] = father, dep[o] = depth, size[o] = 1;for (int i = g2.path[o]; i; i = g2.edge[i].next)if (g2.edge[i].to != father) {if (o >= X) Q[o].push(a[g2.edge[i].to]);dfs1(g2.edge[i].to, depth+1, o);size[o] += size[g2.edge[i].to];if (size[g2.edge[i].to] > size[son[o]]) son[o] = g2.edge[i].to;}if (o > X) a[o] = Q[o].top();
}
void dfs2(int o, int tp) {top[o] = tp, idx[o] = ++pos, b[pos] = o;if (son[o]) dfs2(son[o], tp);for (int i = g2.path[o]; i; i = g2.edge[i].next)if (g2.edge[i].to != fa[o] && g2.edge[i].to != son[o])dfs2(g2.edge[i].to, g2.edge[i].to);
}
int query(int u, int v) {int ans = INF, t;while (top[u] != top[v]) {if (dep[top[u]] < dep[top[v]]) Swap(u, v);t = T.query(1, 1, n, idx[top[u]], idx[u]);ans = Min(ans, t); u = fa[top[u]];}if (dep[u] < dep[v]) Swap(u, v);t = T.query(1, 1, n, idx[v], idx[u]); ans = Min(ans, t);if (v > X) t = T.query(1, 1, n, idx[fa[v]], idx[fa[v]]), ans = Min(ans, t);return ans;
}
void update(int o, int val) {if (fa[o]) Q[fa[o]].erase(a[o]);a[o] = val; T.insert(1, 1, n, idx[o]);if (fa[o]) Q[fa[o]].push(a[o]), a[fa[o]] = Q[fa[o]].top(), T.insert(1, 1, n, idx[fa[o]]);
}
void work() {read(n), read(m), read(q); X = n;for (int i = 1; i <= n; i++) read(a[i]);for (int i = 1; i <= m; i++) read(u), read(v), g1.add(u, v), g1.add(v, u);tarjan(1, 0); dfs1(1, 1, 0); dfs2(1, 1); T.build(1, 1, n);while (q--) {scanf("%s", ch); read(u), read(v);if (ch[0] == 'A') writeln(query(u, v));else update(u, v);}
}
int main() {work(); return 0;
}

转载于:https://www.cnblogs.com/NaVi-Awson/p/8588195.html

[Codeforces 487E]Tourists相关推荐

  1. 业界毒瘤仙人掌一条龙服务

    本slide是为了NJU集训队准备....未完待续... 正经定义 : 无向图中的每条边至多位于一个简单环上,且任意两点可达. 由此可知仙人掌的构造方式很"优美",即生成一棵树,把 ...

  2. [学习笔记]圆方树广义圆方树

    引入 偶尔,我们会遇到一些要在无向图/仙人掌上做的问题,这些问题如果在树上就会比较方便,那么我们就开始考虑能不能把原图等效成一棵树,然后就可以方便地乱搞了? 圆方树就是一种将无向图/仙人掌变成树的数据 ...

  3. 广义圆方树+树链剖分+set(Codeforces Round #278 (Div. 1): E. Tourists)

    前置:双联通分量.圆方树.树链剖分 什是是广义圆方树 圆方树是针对于仙人掌建树,而广义圆方树是针对无向图建树,对于一个无向图 无向图中的所有点 → 广义圆方树中的所有圆点 无向图中的一个双联通分量 → ...

  4. codeforces Round 21 808E. Selling Souvenirs 【dp好题】

    codeforces Round 21 808E. Selling Souvenirs [dp好题] E. Selling Souvenirs time limit per test 2 second ...

  5. CodeForces 375D Tree and Queries

    传送门:https://codeforces.com/problemset/problem/375/D 题意: 给你一颗有根树,树上每个节点都有其对应的颜色,有m次询问,每次问你以点v为父节点的子树内 ...

  6. 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)

    题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...

  7. 【codeforces 812C】Sagheer and Nubian Market

    [题目链接]:http://codeforces.com/contest/812/problem/C [题意] 给你n个物品; 你可以选购k个物品;则 每个物品有一个基础价值; 然后还有一个附加价值; ...

  8. CodeForces 获得数据

    针对程序的输出可以看见 CodeForces :当输入.输出超过一定字符,会隐藏内容 所以:分若干个程序进行输入数据的获取 1. 1 for (i=1;i<=q;i++) 2 { 3 scanf ...

  9. codeforces水题100道 第二十七题 Codeforces Round #172 (Div. 2) A. Word Capitalization (strings)...

    题目链接:http://www.codeforces.com/problemset/problem/281/A 题意:将一个英文字母的首字母变成大写,然后输出. C++代码: #include < ...

最新文章

  1. 阿里巴巴的技术专家,是如何画好架构图的?
  2. 查询提升200倍,ClickHouse你值得拥有!
  3. 求出歌手的得分python_哪位大侠帮我做做python的题目啊,做其中5个就好。跪求啊...
  4. 堆排序(利用最大堆)
  5. java 远程查看电脑磁盘,请问你如何在Java中监视计算机的CPU、内存和磁盘使用情况?...
  6. SAP Fiori Launchpad shell.handleGoHome() - home按钮的实现
  7. Android设计模式之——单例模式
  8. mysql重复记录大于十的数据库_面试官:在使用mysql数据库时,遇到重复数据怎么处理?...
  9. 每天定时自动优化MySQL数据库
  10. SWT FontFieldEditor使用
  11. 1.4 如何防止sql注入
  12. mac install wget
  13. [Python图像处理] 十七.图像锐化与边缘检测之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
  14. c语言编程出彩色告白,C语言告白代码,一闪一闪亮晶晶~
  15. H5-ffmpeg.js压缩视频
  16. uboot 或者 linux 下限制 sata speed
  17. Android Cursor的一些浅显见解
  18. 设计复数类 Complex继承于数字类 Number,私有成员变量包括 double类型的实部rea(父类 Number中已定义)和虚部imag,公有成员方法包括两个构造方法(一个不带参数的和一个带两
  19. 关于Wii的软件制作
  20. Eucalyptus配置管理

热门文章

  1. nginx - 性能优化
  2. Binary Agents
  3. java入门之内部类
  4. 为Eclipse安装主题插件
  5. Andrew Stankevich#39;s Contest (1)
  6. 客户端控件Javascript验证类
  7. Babel下的ES6兼容性与规范
  8. 浅谈函数的重入与不可重入
  9. 将房子卖了五百万,存在银行,靠利息能过日子吗?
  10. 语文到底要不要补课?