zoukankan      html  css  js  c++  java
  • [CodeForces 487E]Tourists

    Link

    Description

    (n)个点,(m)条边的无向连通图,每个点有点权。

    有两种操作:

    • 修改某个点的点权。
    • 询问两点间所有简单路径上点权最小值。

    Solution

    建出圆方树。令方点点权为相邻圆点点权的最小值。那么现在询问就变成查询路径最小值,可以用树剖+线段树解决。

    对于修改,如果修改某个点权值,那么它周围的所有方点权值都要修改,可以被卡成( ext O(n))

    所以改一下思路,考虑到圆方树是一棵树,可以令方点点权为其儿子圆点点权的最小值。这样,修改一个圆点,只需要顺带修改其父亲方点的点权即可。

    对于每方点,用一个multiset维护所有儿子圆点的权值。

    值得注意的是,如果查询时两点lca是方点,那还要查询其父亲圆点的权值。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read(){//be careful for long long!
        register int x=0,f=1;register char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
        while(isdigit(ch)){x=x*10+(ch^'0');ch=getchar();}
        return f?x:-x;
    }
     
    const int N=1e5+10;
    int n,m,q,w[N<<1],cnt,dfc,dfn[N<<1],low[N],stk[N],tp;
    vector<int> re_E[N],E[N<<1];
    #define pb(x) push_back(x)
     
    inline void Tarjan(int nw){
        dfn[nw]=low[nw]=++dfc;stk[++tp]=nw;
        for(int to:re_E[nw])
    	if(!dfn[to]){
    	    Tarjan(to);
    	    low[nw]=min(low[nw],low[to]);
    	    if(low[to]==dfn[nw]){
    		++cnt;
    		for(int x=0;x^to;--tp){
    		    x=stk[tp];
    		    E[x].pb(cnt),E[cnt].pb(x);
    		}
    		E[nw].pb(cnt),E[cnt].pb(nw);
    	    }
    	}
    	else low[nw]=min(low[nw],dfn[to]);
    }
     
    namespace TCP{
        const int _=2e5+10;
        int son[_],siz[_],fa[_],dep[_],tp[_],rol[_];
        multiset<int> W[_>>1];
        struct Segment_tree{
    #define ls(p) p<<1
    #define rs(p) p<<1|1
    	int tr[_<<2];
    	inline void update(int p){tr[p]=min(tr[ls(p)],tr[rs(p)]);return;}
    	inline void Build(int p,int l,int r){
    	    if(l==r){tr[p]=w[rol[l]];return;}
    	    int mid=(l+r)>>1;
    	    Build(ls(p),l,mid),Build(rs(p),mid+1,r);
    	    update(p);
    	}
    	inline void Modify(int p,int l,int r,int pos,int val){
    	    if(l==r){tr[p]=val;return;}
    	    int mid=(l+r)>>1;
    	    if(mid>=pos)Modify(ls(p),l,mid,pos,val);
    	    else Modify(rs(p),mid+1,r,pos,val);
    	    update(p);
    	}
    	inline int Query(int p,int l,int r,int L,int R){
    	    if(L<=l&&r<=R)return tr[p];
    	    int mid=(l+r)>>1,ans=2e9;
    	    if(mid>=L)ans=min(ans,Query(ls(p),l,mid,L,R));
    	    if(mid<R)ans=min(ans,Query(rs(p),mid+1,r,L,R));
    	    return ans;
    	}
        }T;
     
        inline void Dfs_o(int nw,int f=0){
    	siz[nw]=1;dep[nw]=dep[fa[nw]]+1;
    	for(int to:E[nw])
    	    if(to^f){
    		fa[to]=nw;Dfs_o(to,nw);siz[nw]+=siz[to];
    		if(siz[to]>siz[son[nw]])son[nw]=to;
    		if(nw>n)W[nw-n].insert(w[to]);
    	    }
        }
        inline void Dfs_t(int nw){
    	dfn[nw]=++dfc;rol[dfc]=nw;
    	if(!tp[nw])tp[nw]=nw;
    	if(son[nw]){tp[son[nw]]=tp[nw];Dfs_t(son[nw]);}
    	for(int to:E[nw])
    	    if(to^fa[nw]&&to^son[nw])
    		Dfs_t(to);
        }
        inline int lca(int x,int y){
    	int ans=0x7fffffff;
    	while(tp[x]^tp[y]){
    	    if(dep[tp[x]]>=dep[tp[y]])ans=min(ans,T.Query(1,1,dfc,dfn[tp[x]],dfn[x])),x=fa[tp[x]];
    	    else ans=min(ans,T.Query(1,1,dfc,dfn[tp[y]],dfn[y])),y=fa[tp[y]];
    	}
    	if(dep[x]>dep[y])swap(x,y);
    	ans=min(ans,T.Query(1,1,dfc,dfn[x],dfn[y]));
    	if(x>n)ans=min(ans,w[fa[x]]);
    	return ans;
        }
    }using namespace TCP;
     
    int main(){
        n=cnt=read(),m=read(),q=read();
        for(int i=1;i<=n;++i)w[i]=read();
        for(int i=1,u,v;i<=m;++i)u=read(),v=read(),re_E[u].pb(v),re_E[v].pb(u);
        Tarjan(1);memset(dfn,0,sizeof(dfn));dfc=0;
        Dfs_o(1),Dfs_t(1);
        for(int i=n+1;i<=dfc;++i)w[i]=(*W[i-n].begin());
        T.Build(1,1,dfc);
        while(q--){
    	char ch=getchar();
    	switch(ch){
    	case 'C':{
    	    int x=read();
    	    if(x^1){
    		W[fa[x]-n].erase(W[fa[x]-n].find(w[x]));
    		W[fa[x]-n].insert(w[x]=read());
    		T.Modify(1,1,dfc,dfn[fa[x]],(*W[fa[x]-n].begin()));
    	    }
    	    else w[x]=read();
    	    T.Modify(1,1,dfc,dfn[x],w[x]);
    	    break;
    	}
    	case 'A':{
    	    int x=read(),y=read();
    	    printf("%d
    ",TCP::lca(x,y));
    	    break;
    	}
    	}
        }
        return 0;
    }
    
    
  • 相关阅读:
    zoj 3627#模拟#枚举
    Codeforces 432D Prefixes and Suffixes kmp
    hdu 4778 Gems Fight! 状压dp
    CodeForces 379D 暴力 枚举
    HDU 4022 stl multiset
    手动转一下田神的2048
    【ZOJ】3785 What day is that day? ——KMP 暴力打表找规律
    poj 3254 状压dp
    C++中运算符的优先级
    内存中的数据对齐
  • 原文地址:https://www.cnblogs.com/fruitea/p/12080439.html
Copyright © 2011-2022 走看看