CF487E & UOJ30:Tourists——题解
http://codeforces.com/problemset/problem/487/E
https://www.luogu.com.cn/problem/CF487E
(洛谷链接可以看中文题面)
(不会set的脑瘫患者在此)
题不是很难,圆方树先建起来,就不难想到用multiset维护每个方点为周围圆点权值最小值,然后跑一边树链剖分就好了。
但是每次修改圆点万一它旁边有一大堆方点暴力修改肯定会TLE。
所以我们只修改它的父亲方点,这样做的代价就是在查询$(x,y)$时如果$lca(x,y)$是方点那么不要忘了把它的父亲权值考虑在内。
码力下降太严重了
#include<set> #include<cmath> #include<queue> #include<stack> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=2e5+5; const int M=4e5+5; const int INF=1e9; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int u[M],v[M],nxt[M]; int cnt,head[N]; void init(){ cnt=0;memset(head,0,sizeof(head)); } void add(int U,int V){ u[++cnt]=U;v[cnt]=V;nxt[cnt]=head[U];head[U]=cnt; } }e,g; int n,m,T,w[N]; int dfn[N],low[N],to[N],t,l; stack<int>q; void tarjan(int u,int f){ dfn[u]=low[u]=++t; for(int i=g.head[u];i;i=g.nxt[i]){ int v=g.v[i]; if(!dfn[v]){ q.push(i);tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]){ int num;l++; do{ num=q.top();q.pop(); int x=g.u[num],y=g.v[num]; if(to[x]!=l){ to[x]=l; e.add(x,l+n);e.add(l+n,x); } if(to[y]!=l){ to[y]=l; e.add(y,l+n);e.add(l+n,y); } }while(num!=i); } }else if(low[u]>dfn[v]&&f!=v){ q.push(i);low[u]=dfn[v]; } } } inline bool is_square(int x){ return x>n; } multiset<int>minn[N]; int tot,fa[N],pos[N],idx[N],size[N],son[N],dep[N],top[N],val[N]; void dfs1(int u){ size[u]=1; for(int i=e.head[u];i;i=e.nxt[i]){ int v=e.v[i]; if(fa[u]==v)continue; fa[v]=u;dep[v]=dep[u]+1; if(is_square(u))minn[u].insert(w[v]); dfs1(v);size[u]+=size[v]; if(!son[u]||size[son[u]]<size[v])son[u]=v; } } void dfs2(int u,int anc){ pos[u]=++tot;idx[tot]=u;top[u]=anc; if(!son[u])return; dfs2(son[u],anc); for(int i=e.head[u];i;i=e.nxt[i]){ int v=e.v[i]; if(v==fa[u]||v==son[u])continue; dfs2(v,v); } } inline void init(){ dep[1]=1; dfs1(1); dfs2(1,1); } int tr[N<<2]; void build(int a,int l,int r){ if(l==r){ tr[a]=(is_square(idx[l]))? *minn[idx[l]].begin():w[idx[l]]; return; } int mid=(l+r)>>1; build(a<<1,l,mid);build(a<<1|1,mid+1,r); tr[a]=min(tr[a<<1],tr[a<<1|1]); } inline int query(int a,int l,int r,int l1,int r1){ if(r1<l||l1>r)return INF; if(l1<=l&&r<=r1)return tr[a]; int mid=(l+r)>>1; return min(query(a<<1,l,mid,l1,r1),query(a<<1|1,mid+1,r,l1,r1)); } inline void modify(int a,int l,int r,int x){ if(x<l||r<x)return; if(l==r){ tr[a]=(is_square(idx[l]))? *minn[idx[l]].begin():w[idx[l]]; return; } int mid=(l+r)>>1; modify(a<<1,l,mid,x);modify(a<<1|1,mid+1,r,x); tr[a]=min(tr[a<<1],tr[a<<1|1]); } inline int qry(int x,int y){ int ans=INF; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); ans=min(ans,query(1,1,n+l,pos[top[x]],pos[x])); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans=min(ans,query(1,1,n+l,pos[x],pos[y])); return is_square(x)?min(ans,query(1,1,n+l,pos[fa[x]],pos[fa[x]])):ans; } inline void mdy(int x,int y){ if(fa[x]){ minn[fa[x]].insert(y); minn[fa[x]].erase(minn[fa[x]].find(w[x])); modify(1,1,n+l,pos[fa[x]]); } w[x]=y; modify(1,1,n+l,pos[x]); } int main(){ n=read(),m=read(),T=read(); for(int i=1;i<=n;i++)w[i]=read(); for(int i=1;i<=m;i++){ int u=read(),v=read(); g.add(u,v);g.add(v,u); } tarjan(1,0); init();build(1,1,n+l); for(int i=1;i<=T;i++){ char c=getchar(); int x=read(),y=read(); if(c=='C')mdy(x,y); if(c=='A')printf("%d\n",qry(x,y)); } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++