zoukankan      html  css  js  c++  java
  • Codeforces278E Tourists

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    给定一张无向图,有点权,要支持单点修改点权和询问从一个点到另一个点不重复经过节点的路径上点权最小值的最小值。

    n,m<=10^5

    考虑求出图的点双连通分量,然后每个点向所有包含他的点双连边,这样我们可以得到一棵树。

    询问就变成了询问与树上两点间路径上的点相邻的点中权值的最小值。

    我们考虑对每个点双开一个堆,把所有儿子的信息扔进去。这样但点修改只需要修改它父亲那个点双就行了。

    然后用树剖+线段树来支持查询即可。注意特判lca的父亲节点。

    复杂度O(nlog^2n)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<map>
    #define P(x,y) make_pair(min(x,y),max(x,y))
    #define pa pair<int,int>
    #define MN 200000
    #define N 262144
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    pa q[MN*2+5];map<pa,bool> mp;vector<int> v[MN+5];priority_queue<pa,vector<pa>,greater<pa> > s[MN+5];
    int n,m,Q,tp=0,b[MN+5],head[MN+5],dfn[MN+5],low[MN+5],mark[MN+5],dn=0,cnt=0,size[MN+5];
    int fa[MN+5],w[MN+5],vis[MN+5],num=0,bel[MN+5],dep[MN+5],top[MN+5],mx[MN+5],T[N*2+5];
    struct edge{int to,next;}e[MN*2+5];
    inline void ins(int f,int t)
    {
        e[++cnt]=(edge){t,head[f]};head[f]=cnt;
        e[++cnt]=(edge){f,head[t]};head[t]=cnt;    
    }
    inline void Ins(int f,int t)
    {
        v[f].push_back(t);
        v[t].push_back(f);    
    }
    void Tarjan(int x,int fa)
    {
        dfn[x]=low[x]=++dn;int son=0;
        for(int i=head[x];i;i=e[i].next)
            if(e[i].to!=fa)
            {
                if(!dfn[e[i].to]) 
                {
                    ++son;
                    q[++tp]=make_pair(x,e[i].to),Tarjan(e[i].to,x);
                    low[x]=min(low[x],low[e[i].to]);
                    if(low[e[i].to]>=dfn[x])
                    {
                        b[x]=1;++num;
                        while(q[tp+1]!=make_pair(x,e[i].to))
                        {
                            int a=q[tp].first,b=q[tp].second;
                            if(bel[a]!=num) Ins(a,num+n);
                            if(bel[b]!=num) Ins(b,num+n);
                            --tp;bel[a]=num;bel[b]=num;
                        }
                    }
                }
                else 
                {
                    low[x]=min(low[x],dfn[e[i].to]);
                    if(dfn[x]>dfn[e[i].to]) q[++tp]=make_pair(x,e[i].to);    
                }
            }
        if(son==1&&!fa) b[x]=0;
    }
    void Pre(int x,int f)
    {
        fa[x]=f;size[x]=1;mx[x]=0;
        for(int i=0;i<v[x].size();++i)
            if(v[x][i]!=f)
            {
                dep[v[x][i]]=dep[x]+1;
                Pre(v[x][i],x);
                size[x]+=size[v[x][i]];
                if(size[v[x][i]]>size[mx[x]]) mx[x]=v[x][i];
            }
    }
    
    void Dfs(int x,int Tp)
    {
        top[x]=Tp;dfn[x]=++dn;
        if(mx[x]) Dfs(mx[x],Tp);
        for(int i=0;i<v[x].size();++i)
            if(v[x][i]!=mx[x]&&v[x][i]!=fa[x])
                Dfs(v[x][i],v[x][i]);
    }
    void Renew(int x,int k){for(T[x+=N]=k;x>>=1;)T[x]=min(T[x<<1],T[x<<1|1]);}
    int Query(int l,int r)
    {
        int mx=1e9;    
        for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1) mx=min(mx,T[l+1]);
            if( r&1) mx=min(mx,T[r-1]);    
        }
        return mx;
    }
    void Add(int x,int v,int k)
    {
        ++vis[v];
        s[x].push(make_pair(k,v));    
        while(!s[x].empty()&&w[s[x].top().second]!=s[x].top().first) s[x].pop();
        int K=s[x].size()?s[x].top().first:0;Renew(dfn[x],K); 
    }
    int Solve(int x,int y)
    {
        int mx=1e9;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            mx=min(mx,Query(dfn[top[x]],dfn[x]));
            x=fa[top[x]];
        }
        if(dfn[x]>dfn[y]) swap(x,y);
        mx=min(mx,Query(dfn[x],dfn[y]));
        if(x>n&&fa[x]) mx=min(mx,w[fa[x]]);
        return mx;
    }
    char st[10];
    int main()
    {
        n=read();m=read();Q=read();
        for(int i=1;i<=n;++i) w[i]=read();
        for(int i=1;i<=m;++i) ins(read(),read());
        Tarjan(1,0);memset(T,63,sizeof(T));
        dn=0;Pre(1,0);Dfs(1,1);
        for(int i=1;i<=n;++i) 
        {
            Renew(dfn[i],w[i]);
            if(fa[i]) Add(fa[i],i,w[i]);
        }
        for(int i=1;i<=Q;++i)
        {
            scanf("%s",st+1);int x=read(),y=read();
            if(st[1]=='A')  printf("%d
    ",Solve(x,y));
            else 
            {
                w[x]=y,Renew(dfn[x],y);
                if(fa[x]) Add(fa[x],x,y);
            }
        }
        return 0;
    }
  • 相关阅读:
    Java 中的 匿名类
    spring boot 中容器 Jetty、Tomcat、Undertow
    微信小程序-动态设置背景色navigationBarBackgroundColor的值
    vue el-tree:默认展开第几级节点
    safarai
    微信小程序-输入框输入文字后,将光标移到文字中间,接着输入文字后光标又自动跳到最后
    微信小程序-WebSocket应用
    微信小程序-聊天列表-角标
    SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data错误的解决
    button 去掉原生边框
  • 原文地址:https://www.cnblogs.com/FallDream/p/cf278e.html
Copyright © 2011-2022 走看看