题目大意:

给定一个无向图,操作一可以修改一个点的点权,操作二询问从x到y的点不重复路径中的点权最小值。

思路:

无向图询问点不重复路径中的点权最小值,路径的条数很多,但是我们发现如果路上有两点在一个点双内,那么这两点之间的路径是可以经过这个点双内的任意一点而获得这个点双之内的最小值的,所以只需要对原图建出圆方树就好了。
建出圆方树之后圆点为原来的权值,方点为它周围所有圆点的权值的最小值,也就是它代表的点双的最小值。然后用树链剖分去维护。
但是发现一个问题,就是一个割点可能属于很多个点双,如果修改了一个割点的权值,那么相应的,它周围所有的方点的权值都要更新,这样显然复杂度就不对了。
又是一个小技巧,把圆方树固定了根结点之后,每一个方点只维护它所有儿子的权值,也就是每一个圆点的权值只在它父亲方点那里维护。如果在跳链的时候跳到了这个圆点的儿子方点,那么要么就是继续往上跳,否则这里就是公共祖先,如果继续往上跳的话就刚好把这个圆点算在了内部,如果这是公共祖先的话就在询问的时候特判它父亲的圆点的权值。
所以每一个圆点的修改只需要更新一个方点了,复杂度就很正了。

#include<bits/stdc++.h>#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;using namespace std;void File(){freopen("uoj30.in","r",stdin);freopen("uoj30.out","w",stdout);
}template<typename T>void read(T &_){T __=0,mul=1; char ch=getchar();while(!isdigit(ch)){if(ch=='-')mul=-1;ch=getchar();}while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();_=__*mul;
}const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
int n,m,q,w[maxn<<1],tot;
int beg[maxn],to[maxn<<1],las[maxn<<1],cnte=1;
vector<int>G[maxn<<1];
int dfn[maxn],low[maxn],cnt_dfn;
stack<int>stk;
multiset<int>st[maxn<<1];
multiset<int>::iterator it;void add(int u,int v){las[++cnte]=beg[u]; beg[u]=cnte; to[cnte]=v;las[++cnte]=beg[v]; beg[v]=cnte; to[cnte]=u;
}void tarjan(int u,int f){stk.push(u);low[u]=dfn[u]=++cnt_dfn;for(int i=beg[u];i;i=las[i]){if(to[i]==f)continue;if(!dfn[to[i]]){tarjan(to[i],u);low[u]=min(low[u],low[to[i]]);if(low[to[i]]>=dfn[u]){++tot;for(int p;p!=to[i];stk.pop()){p=stk.top();G[tot].push_back(p);G[p].push_back(tot);}G[tot].push_back(u);G[u].push_back(tot);}}else low[u]=min(low[u],dfn[to[i]]);}
}void dfs(int u,int f){for(int sz=G[u].size()-1,i=0;i<=sz;++i){if(G[u][i]==f)continue;//cout<<u<<" "<<G[u][i]<<endl;if(u>n)st[u].insert(w[G[u][i]]);dfs(G[u][i],u);}if(u>n)it=st[u].begin(),w[u]=*it;//cout<<u<<" "<<w[u]<<endl;
}struct Segment_Tree{
#define mid ((l+r)>>1)
#define lc rt<<1
#define rc rt<<1|1
#define lson lc,l,mid
#define rson rc,mid+1,rint Min[maxn<<3];void update(int rt,int l,int r,int pos,int x){if(l==r){Min[rt]=x; return;}if(pos<=mid)update(lson,pos,x);else update(rson,pos,x);Min[rt]=min(Min[lc],Min[rc]);}int query(int rt,int l,int r,int L,int R){if(L<=l && r<=R)return Min[rt];int ret=inf;if(L<=mid)ret=query(lson,L,R);if(R>=mid+1)ret=min(ret,query(rson,L,R));return ret;}
}T;int dep[maxn<<1],fa[maxn<<1],son[maxn<<1],siz[maxn<<1],top[maxn<<1],in[maxn<<1],cnt_tree;void dfs1(int u,int f){dep[u]=dep[f]+1; siz[u]=1; fa[u]=f;for(int sz=G[u].size()-1,i=0;i<=sz;++i){if(G[u][i]==f)continue;dfs1(G[u][i],u);siz[u]+=siz[G[u][i]];if(siz[G[u][i]]>siz[son[u]])son[u]=G[u][i];}
}void dfs2(int u,int tp){in[u]=++cnt_tree; top[u]=tp;T.update(1,1,tot,in[u],w[u]);if(son[u])dfs2(son[u],tp);for(int sz=G[u].size()-1,i=0;i<=sz;++i){if(G[u][i]==fa[u] || G[u][i]==son[u])continue;dfs2(G[u][i],G[u][i]);}
}void modify(int u,int x){T.update(1,1,tot,in[u],x);if(fa[u]){st[fa[u]].insert(x);it=st[fa[u]].find(w[u]);st[fa[u]].erase(it);it=st[fa[u]].begin();w[fa[u]]=*it; T.update(1,1,tot,in[fa[u]],w[fa[u]]);}w[u]=x;
}int solve(int u,int v){int Min=inf;while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]])swap(u,v);Min=min(Min,T.query(1,1,tot,in[top[u]],in[u]));u=fa[top[u]];}if(dep[u]<dep[v])swap(u,v);Min=min(Min,T.query(1,1,tot,in[v],in[u]));if(fa[v] && fa[v]<=n)Min=min(Min,w[fa[v]]);return Min;
}void init(){read(n); read(m); read(q);REP(i,1,n)read(w[i]);int u,v;REP(i,1,m)read(u),read(v),add(u,v);tot=n; tarjan(1,0); dfs(1,0); memset(T.Min,63,sizeof(T.Min));dfs1(1,0); dfs2(1,1);
}void work(){char s[5];int u,v;REP(i,1,q){scanf("%s",s);read(u); read(v);if(s[0]=='A')printf("%d\n",solve(u,v));else modify(u,v);}
}int main(){File();init();work();return 0;
}

[uoj30][CF Round #278]Tourists——树链剖分+圆方树相关推荐

  1. [树链剖分][圆方树] Jzoj P5909 跑商

    Description 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖 ...

  2. BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2157 是 hydro 的 BZOJ ...

  3. Luogu P5556 圣剑护符(线性基,树链剖分,线段树)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Problem 小L 和 小K 面前的圣剑由 nnn 块护符组成,分别编号为 1,2,-,n1,2,\ ...

  4. BZOJ 2402 陶陶的难题II (树链剖分、线段树、凸包、分数规划)

    毒瘤,毒瘤,毒瘤-- \(30000\)这个数据范围,看上去就是要搞事的啊... 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2402 ...

  5. [Bzoj4196] [NOI2015] 软件包管理器 [树链剖分,线段树]

    题解摘要:树链剖分后用线段树区间查询修改,对于安装软件,将改点到根的路径全部变为1,对于卸载软件,将子树清空.注意边界,编号是从0开始的,容易漏掉树根. 第一次写树剖- 1 #include < ...

  6. Tree HDU - 6547 (树链剖分,线段树)

    wls 有三棵树,树上每个节点都有一个值 ai,现在有 2 种操作: 将一条链上的所有节点的值开根号向下取整: 求一条链上值的和: 链的定义是两点之间的最短路. Input 第一行两个数 n, q 分 ...

  7. 兰州大学第一届 飞马杯 ★★快乐苹果树★★ 树链剖分 + 懒标记 + 树状数组

    传送门 文章目录 题意: 思路: 题意: 思路: 第一次听说树链剖分能在fa[top[i]]fa[top[i]]fa[top[i]]的地方加懒标记,学到了学到了. 首先不能被题目吓住,这个题目仔细剖析 ...

  8. 清明梦超能力者黄YY[树链剖分+扫描线,线段树合并]

    清明梦超能力者黄YY 题目连接 https://www.nowcoder.com/acm/contest/206/I 暂时有两种做法. 算法一 涉及:树链剖分,扫描线 在一个线段的情况下,我们可以把一 ...

  9. hdu5111 树链剖分,主席树

    hdu5111 链接 hdu 思路 先考虑序列上如何解决. 1 3 2 5 4 1 2 4 5 3 这个序列变成 1 2 3 4 5 1 3 5 5 2 是对答案没有影响的(显然). 然后查询操作\( ...

  10. HDU 3966 树链剖分后线段树维护

    题意: 一棵树, 操作1.$path(a,b)$之间的点权$+k$ 操作2.单点查询 题解: 树链剖分即可,注意代码细节,双向映射 主要是记录一下板子 #include <string.h> ...

最新文章

  1. Android之选项菜单创建
  2. linux 下 oracle 10.2.0.1 32bit netca报错
  3. php 随机指定位数,php生成一个可选位数的随机码
  4. service启动activity_「 Android 10 四大组件 」系列—Service 的 quot; 启动流程 quot;
  5. java 服务器 时间_java 获取服务器的时间,年月日时分秒
  6. PostgreSQL 性能优化方法 - 1
  7. Nginx防盗链、访问控制、解析php相关配置、Nginx代理
  8. 绿坝即将登场,好戏就要开演
  9. Chisel Bootcamp安装说明
  10. 数字中国城市巡礼之乌兰察布:红山口上的“草原硅谷”
  11. 电机与拖动:异步交流电动机改变电压,转子电阻及频率的机械特性曲线(Matlab实现方法)
  12. php获取银行logo,PHP实现根据银行卡号判断银行
  13. python关于二手房的课程论文_python爬取链家二手房信息
  14. SSL证书中的128位加密和256位加密有何区别?
  15. html 拉伸幕,html 对 div 进行 拉伸 拖拽
  16. 中医药大学远程教育计算机,《中医药大学远程教育计算机作业 1-7》.doc
  17. 因为这5大工具,同事直呼我时间管理小王子
  18. 人工智能最全学习路线
  19. JAVA:实现LongestPalindromicSubsequence最长回文子序列算法(附完整源码)
  20. 树状数组入门——以洛谷3374为例

热门文章

  1. Dynamics CRM 审批流引擎
  2. halcon与C#混合编程(三)数字识别
  3. Catboost参数全集
  4. 天眼查、企查查APP的Authorized值和sign值破解思路记载
  5. Spring AOP内部方法调用代理失效
  6. html5 css3 入门教程
  7. php faker,laravel使用Faker数据填充的实现方法
  8. P1361 小猫爬山 bool dfs
  9. ES6(十八)Module
  10. [大数据技术] 淘宝双11数据分析与预测实验