[Codeforces 487E]Tourists/[JZOJ4691]旅行/[UOJ#30]Tourists
来源:互联网 发布:替代 usleep windows 编辑:程序博客网 时间:2024/06/11 04:05
题目大意
给定一个有
有
题目分析
第一眼看见这题应该有个很显然的想法,就是点双连通分量缩点然后树链剖分。
但是实际想一想,细节还是很多的,怎样构图才能保证正确性而且修改的时候不会T?
在这里我们使用这样一种方法:对于每一个点双连通分量,我们建一个新建点储存点双所有点的最小权值,然后该点向点双内所有
注意到这棵树一定是普通点连向新建点连向普通点这样交替。修改的时候我们修改这个点自身的权值,还要把这个点所属的新建点(父亲节点)修改了。查询的时候呢?首先先查询两点之间路径的最小值,然后如果两点
为什么这样是对的呢?因为查询的时候,除了最顶端
关于怎么维护点双内最小值,对每一个新建点开一个
时间复杂度
代码实现
#include <algorithm>#include <iostream>#include <climits>#include <cstring>#include <cstdio>#include <cctype>#include <cmath>#include <stack>#include <set>using namespace std;typedef multiset<int>::iterator ptr;const int INF=INT_MAX;const int N=100050;const int V=N<<1;const int M=N<<1;const int E=M<<1;const int EL=V<<1;const int LGEL=19;multiset<int> bst[V];struct G{ int next[E],tov[E]; int last[V]; int tot; void insert(int x,int y){tov[++tot]=y,next[tot]=last[x],last[x]=tot;}}g,t;int size[V],hea[V],prt[V],fa[V],DFN[V],LOW[N],val[V],high[V],pos[V];int n,m,q,all,idx,el,lgel;int rmq[EL][LGEL];int euler[EL];stack<int> S;struct segment_tree{ int v[V<<2]; void update(int x){v[x]=min(v[x<<1],v[x<<1|1]);} void modify(int x,int y,int l,int r,int edit) { if (l==r) { v[x]=edit; return; } int mid=l+r>>1; if (y<=mid) modify(x<<1,y,l,mid,edit); else modify(x<<1|1,y,mid+1,r,edit); update(x); } int query(int x,int st,int en,int l,int r) { if (st==l&&en==r) return v[x]; int mid=l+r>>1; if (en<=mid) return query(x<<1,st,en,l,mid); else if (mid+1<=st) return query(x<<1|1,st,en,mid+1,r); else return min(query(x<<1,st,mid,l,mid),query(x<<1|1,mid+1,en,mid+1,r)); }}T;void tarjan(int x,int fr){ DFN[x]=LOW[x]=++idx,S.push(x); for (int i=g.last[x],y;i;i=g.next[i]) if (!DFN[y=g.tov[i]]) { tarjan(y,x); LOW[x]=min(LOW[x],LOW[y]); if (LOW[y]>=DFN[x]) { int sp=++all; t.insert(x,sp); for (int u;;) { u=S.top(),S.pop(),t.insert(sp,u),bst[sp].insert(val[u]); if (u==y) break; } } } else if (y!=fr) LOW[x]=min(LOW[x],DFN[y]);}void dfs(int x){ size[x]=1,hea[x]=0,rmq[pos[euler[++el]=x]=el][0]=x; for (int i=t.last[x],y;i;i=t.next[i]) { high[y=t.tov[i]]=high[x]+1,fa[y]=x,dfs(y),euler[++el]=x,rmq[el][0]=x,size[x]+=size[y]; if (!hea[x]||size[hea[x]]<size[y]) hea[x]=y; }}void build(int x,int fr){ DFN[x]=++idx,prt[x]=fr; if (!hea[x]) return; build(hea[x],fr); for (int i=t.last[x],y;i;i=t.next[i]) if ((y=t.tov[i])!=hea[x]) build(y,y);}void pre(){ lgel=trunc(log(el)/log(2)); for (int j=1;j<=lgel;j++) for (int i=1;i+(1<<j)-1<=el;i++) rmq[i][j]=high[rmq[i][j-1]]<high[rmq[i+(1<<j-1)][j-1]]?rmq[i][j-1]:rmq[i+(1<<j-1)][j-1]; for (int i=n+1;i<=all;i++) val[i]=*bst[i].begin(); for (int i=1;i<=all;i++) T.modify(1,DFN[i],1,idx,val[i]);}int getrmq(int l,int r){ int lgr=trunc(log(r-l+1)/log(2)); return high[rmq[l][lgr]]<high[rmq[r-(1<<lgr)+1][lgr]]?rmq[l][lgr]:rmq[r-(1<<lgr)+1][lgr];}int lca(int x,int y){ if ((x=pos[x])>(y=pos[y])) swap(x,y); return getrmq(x,y);}int getans(int x,int y){ int z=lca(x,y),ret=INF; for (int u=prt[x];prt[x]!=prt[z];x=fa[u],u=prt[x]) ret=min(ret,T.query(1,DFN[u],DFN[x],1,idx)); ret=min(ret,T.query(1,DFN[z],DFN[x],1,idx)); for (int u=prt[y];prt[y]!=prt[z];y=fa[u],u=prt[y]) ret=min(ret,T.query(1,DFN[u],DFN[y],1,idx)); ret=min(ret,T.query(1,DFN[z],DFN[y],1,idx)); if (z>n) ret=min(ret,val[fa[z]]); return ret;}int main(){ freopen("tourists.in","r",stdin),freopen("tourists.out","w",stdout); scanf("%d%d%d",&n,&m,&q); for (int i=1;i<=n;i++) scanf("%d",&val[i]); for (int i=1,u,v;i<=m;i++) { scanf("%d%d",&u,&v); g.insert(u,v),g.insert(v,u); } all=n,tarjan(1,0),high[1]=1,fa[1]=0,dfs(1),idx=0,memset(DFN,0,sizeof DFN),build(1,1),pre(); for (int i=1,a,b;i<=q;i++) { char opt=getchar(); while (!isalpha(opt)) opt=getchar(); scanf("%d%d",&a,&b); if (opt=='C') { if (fa[a]) bst[fa[a]].erase(bst[fa[a]].find(val[a])); val[a]=b,T.modify(1,DFN[a],1,idx,val[a]); if (fa[a]) bst[fa[a]].insert(val[a]),val[fa[a]]=*bst[fa[a]].begin(),T.modify(1,DFN[fa[a]],1,idx,val[fa[a]]); } else printf("%d\n",getans(a,b)); } fclose(stdin),fclose(stdout); return 0;}
0 0
- [Codeforces 487E]Tourists/[JZOJ4691]旅行/[UOJ#30]Tourists
- CodeForces 487E UOJ 30 Tourists Tarjan + 树链剖分
- CodeForces 487E Tourists
- CodeForces - 487E Tourists
- Codeforces 487E Tourists
- CF 487E Tourists(JZOJ4691 旅行) 树链剖分维护点双连通分量信息
- 【codeforces】487E. Tourists 点双连通+树链剖分
- 【UOJ #30】【CF Round #278】Tourists
- codeforces E. Tourists (树链剖分+tarjan)
- codeforces 286D Tourists
- [点双连通分量 缩点 树链剖分] Codeforces 487E #278 (Div. 1) E. Tourists
- 【题解】[codeforces round #198 div2]Tourists problem
- UOJ #30. 【CF Round #278】Tourists Tarjan+树链剖分
- CF286D/bzoj-4223 Tourists
- UOJ30——【CF Round #278】Tourists
- [Codeforces487E]Tourists(Tarjan+树链剖分+STL)
- GYM 100883 H.tourists(一元线性同余方程)
- Boracay is loved by tourists along with the price is inexpensive than Manila
- hdu5867 中位数
- viewpager画小圆点
- Centos6.7操作系统mysql-5.5cmake 源码编译安装
- 开通
- ffmpeg主要数据结构及其之间的关系
- [Codeforces 487E]Tourists/[JZOJ4691]旅行/[UOJ#30]Tourists
- Android Studio创建JNI项目(一)
- 模仿 LED 灯的滚动文字效果
- 自动轮播、解析数据
- 数据结构实验之队列一:排队买饭
- android 中的异步加载机制 使用AsyncTask类
- border-box之全局问题解析
- 第一部分:音频播放
- window.onload和$(document).ready()的区别