博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CF487E Tourists
阅读量:6843 次
发布时间:2019-06-26

本文共 3539 字,大约阅读时间需要 11 分钟。

圆方树还真是个神奇的玩意儿……

我们先考虑询问,对一个点双来说,经过这个点双的时候能走到的最小值肯定是这个点双内的最小值,那么只要对于每个点双把它的权值设成它里面所有点的最小值,那么就可以在建出广义圆方树之后用树链剖分求出路径最小值了
然而这里有询问,一个想法是对每个点双开一个multiset,每次更改某一个点的值的时候就更改它在的所有点双,再维护即可
于是出题人不说话并丢给了你一个菊花图
菊花的话……根节点在所有的点双里(两个点也算一个点双),那么更改复杂度怕是要上天……
然后接下来是一波骚操作:对于每个点双,我们不维护它的父亲节点的答案,那么查询的时候只要特判一下LCA是不是点双然后用它的父亲的权值更新一下。而且对于每一个修改,我们只要更新它的父亲点双的multiset就可以了
于是总的复杂度为\(O(nlog^2n)\)

//minamoto#include
#define ll long long#define inf 0x3f3f3f3f#define fp(i,a,b) for(register int i=a,I=b+1;i
I;--i)#define go(T,u) for(register int i=T.head[u],v=T.e[i].v;i;i=T.e[i].nx,v=T.e[i].v)#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)inline int max(const int &x,const int &y){return x>y?x:y;}inline int min(const int &x,const int &y){return x
'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f;}inline char getop(){char ch;while((ch=getc())!='A'&&ch!='C');return ch;}char sr[1<<21],z[20];int C=-1,Z=0;inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}void print(int x){ if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++C]=z[Z],--Z);sr[++C]='\n';}const int N=5e5+5;struct eg{int v,nx;};struct node{ eg e[N<<1];int head[N],tot; inline void add(int u,int v){ e[++tot]={v,head[u]},head[u]=tot; e[++tot]={u,head[v]},head[v]=tot; }}G,T;multiset
s[N];int w[N],n,m,q,tot,x;int dfn[N],low[N],st[N],tim,stop;void tarjan(int u){ dfn[u]=low[u]=++tim,st[++stop]=u; go(G,u){ if(!dfn[v]){ tarjan(v),low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]){ T.add(++tot,u); do{x=st[stop--],T.add(tot,x);}while(v!=x); } }else low[u]=min(low[u],dfn[v]); }}int t[N<<2];#define ls (p<<1)#define rs (p<<1|1)void update(int p,int l,int r,int x,int w){ if(l==r)return (void)(t[p]=w);int mid=(l+r)>>1; x<=mid?update(ls,l,mid,x,w):update(rs,mid+1,r,x,w); t[p]=min(t[ls],t[rs]);}int query(int p,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r)return t[p]; int res=inf,mid=(l+r)>>1; if(ql<=mid)res=min(res,query(ls,l,mid,ql,qr)); if(qr>mid)res=min(res,query(rs,mid+1,r,ql,qr)); return res;}int fa[N],dd[N],rk[N],sz[N],son[N],top[N],dep[N],num;void dfs1(int u){ sz[u]=1,dep[u]=dep[fa[u]]+1;if(u<=n&&fa[u])s[fa[u]].insert(w[u]); go(T,u)if(v!=fa[u]){ fa[v]=u,dfs1(v),sz[u]+=sz[v]; if(sz[v]>sz[son[u]])son[u]=v; }}void dfs2(int u,int t){ top[u]=t,dd[u]=++num,rk[num]=u;if(!son[u])return; dfs2(son[u],t); go(T,u)if(v!=fa[u]&&v!=son[u])dfs2(v,v);}int query(int u,int v){ int res=inf; while(top[u]!=top[v]){ if(dep[top[u]]
dep[v])swap(u,v); res=min(res,query(1,1,tot,dd[u],dd[v])); return u<=n?res:min(res,w[fa[u]]);}void modify(int u,int ww){ if(fa[u]){ s[fa[u]].erase(s[fa[u]].find(w[u])); s[fa[u]].insert(ww); update(1,1,tot,dd[fa[u]],*s[fa[u]].begin()); }w[u]=ww,update(1,1,tot,dd[u],ww);}int main(){// freopen("testdata.in","r",stdin); int u,v; tot=n=read(),m=read(),q=read(),w[0]=inf; fp(i,1,n)w[i]=read(); fp(i,1,m)u=read(),v=read(),G.add(u,v); tarjan(1),dfs1(1),dfs2(1,1); fp(i,1,n)update(1,1,tot,dd[i],w[i]); fp(i,n+1,tot)update(1,1,tot,dd[i],*s[i].begin()); char op; while(q--){ op=getc(),u=read(),v=read(); op=='C'?modify(u,v):print(query(u,v)); }return Ot(),0;}

转载于:https://www.cnblogs.com/bztMinamoto/p/10038442.html

你可能感兴趣的文章