zoukankan      html  css  js  c++  java
  • 题解 CF487E 【Tourists】

    若从 (x)(y) 的任意一条路径经过了一个点双连通分量,则从 (x)(y) 一定可以经过该点双连通分量中的每一个点。

    用广义圆方树来维护一般无向图,每个方点的权值为其相邻的圆点的权值的最小值,然后可以用树剖来修改和查询。

    但是这样修改的复杂度是不正确的,若一个圆点相邻有许多方点,像菊花图一样,那么复杂度是无法接受的。

    考虑更改方点的权值定义,权值改为在圆方树上的其儿子权值的最小值。这样修改一个圆点时,只用考虑其父亲方点的权值的变化,这样修改复杂度就正确了。

    在每个方点上用 (multiset) 来维护其儿子的权值,查询时两点的 (lca) 若为方点,则还要考虑其父亲圆点的贡献。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 400010
    #define maxm 1600010
    #define inf 2000000000
    #define ls (cur<<1)
    #define rs (cur<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,m,q,tot,dfn_cnt,cnt,root=1;
    int val[maxn],dfn[maxn],low[maxn],st[maxn];
    int fa[maxn],de[maxn],siz[maxn],son[maxn],top[maxn],rev[maxn],mi[maxm];
    vector<int> ve[maxn];
    multiset<int> s[maxn];
    char opt[5];
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to)
    {
        e[++edge_cnt]=(edge){to,head[from]};
        head[from]=edge_cnt;
    }
    void addedge(int x,int y)
    {
        ve[x].push_back(y);
    }
    void tarjan(int x)
    {
        dfn[x]=low[x]=++dfn_cnt,st[++cnt]=x;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(!dfn[y])
            {
                tarjan(y),low[x]=min(low[x],low[y]);
                if(dfn[x]<=low[y])
                {
                    tot++;
                    int now;
                    do
                    {
                        now=st[cnt--];
                        addedge(tot,now),addedge(now,tot);
                    }while(now!=y);
                    addedge(tot,x),addedge(x,tot);
                }
            }
            else low[x]=min(low[x],dfn[y]);
        }
    }
    void dfs_son(int x,int fath)
    {
        de[x]=de[fath]+1,siz[x]=1,fa[x]=fath,s[fath].insert(val[x]);
        for(int i=0;i<ve[x].size();++i)
        {
            int  y=ve[x][i];
            if(y==fath) continue;
            dfs_son(y,x),siz[x]+=siz[y];
            if(siz[y]>siz[son[x]]) son[x]=y;
        }
    }
    void dfs_chain(int x,int tp)
    {
        dfn[x]=++dfn_cnt,rev[dfn_cnt]=x,top[x]=tp;
        if(son[x]) dfs_chain(son[x],tp);
        for(int i=0;i<ve[x].size();++i)
        {
            int y=ve[x][i];
            if(dfn[y]) continue;
            dfs_chain(y,y);
        }
    }
    void build(int l,int r,int cur)
    {
        if(l==r)
        {
            int x=rev[l];
            if(x<=n) mi[cur]=val[x];
            else mi[cur]=*s[x].begin();
            return;
        }
        build(l,mid,ls),build(mid+1,r,rs);
        mi[cur]=min(mi[ls],mi[rs]);
    }
    void modify(int l,int r,int pos,int v,int cur)
    {
        if(l==r)
        {
            mi[cur]=v;
            return;
        }
        if(pos<=mid) modify(l,mid,pos,v,ls);
        else modify(mid+1,r,pos,v,rs);
        mi[cur]=min(mi[ls],mi[rs]);
    }
    int query(int L,int R,int l,int r,int cur)
    {
        if(L<=l&&R>=r) return mi[cur];
        int v=inf;
        if(L<=mid) v=min(v,query(L,R,l,mid,ls));
        if(R>mid) v=min(v,query(L,R,mid+1,r,rs));
        return v;
    }
    int ask(int x,int y)
    {
        int v=inf;
        while(top[x]!=top[y])
        {
            if(de[top[x]]<de[top[y]]) swap(x,y);
            v=min(v,query(dfn[top[x]],dfn[x],1,tot,root));
            x=fa[top[x]];
        }
        if(dfn[x]>dfn[y]) swap(x,y);
        v=min(v,query(dfn[x],dfn[y],1,tot,root));
        if(x>n) v=min(v,val[fa[x]]);
        return v;
    }
    int main()
    {
        read(n),read(m),read(q),tot=n,val[0]=inf;
        for(int i=1;i<=n;++i) read(val[i]);
        for(int i=1;i<=m;++i)
        {
            int x,y;
            read(x),read(y);
            add(x,y),add(y,x);
        }
        tarjan(1),dfn_cnt=0,memset(dfn,0,sizeof(dfn));
        dfs_son(1,0),dfs_chain(1,1),build(1,tot,root);
        while(q--)
        {
            int x,y;
            scanf("%s",opt),read(x),read(y);
            if(opt[0]=='C')
            {
                s[fa[x]].erase(s[fa[x]].find(val[x]));
                s[fa[x]].insert(y),val[x]=y;
                modify(1,tot,dfn[x],y,root);
                modify(1,tot,dfn[fa[x]],*s[fa[x]].begin(),root);
            }
            else printf("%d
    ",ask(x,y));
        }
        return 0;
    }
    
  • 相关阅读:
    【转载】 TensorFlow函数:tf.Session()和tf.Session().as_default()的区别
    【转载】 TensorFlow学习——tf.GPUOptions和tf.ConfigProto用法解析
    【转载】 tf.ConfigProto和tf.GPUOptions用法总结
    【转载】 tf.cond() ----------------------(tensorflow 条件判断语句 if.......else....... )
    【转载】 os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" os.environ["CUDA_VISIBLE_DEVICES"] = "0" (---------tensorflow中设置GPU可见顺序和选取)
    nodejs调试
    cocos2d-js V3.0 V3.1使用DragonBones
    转:Flash 插件面板 DragonBonesDesignPanel 的绿色安装方法
    createjs入门
    cocos2d-js 入门 (主要是HTML5)
  • 原文地址:https://www.cnblogs.com/lhm-/p/13376084.html
Copyright © 2011-2022 走看看