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;
    }
  • 相关阅读:
    Druid 使用 Kafka 将数据载入到 Kafka
    Druid 使用 Kafka 数据加载教程——下载和启动 Kafka
    Druid 集群方式部署 —— 启动服务
    Druid 集群方式部署 —— 端口调整
    Druid 集群方式部署 —— 配置调整
    Druid 集群方式部署 —— 配置 Zookeeper 连接
    Druid 集群方式部署 —— 元数据和深度存储
    Druid 集群方式部署 —— 从独立服务器部署上合并到集群的硬件配置
    Druid 集群方式部署 —— 选择硬件
    Druid 独立服务器方式部署文档
  • 原文地址:https://www.cnblogs.com/FallDream/p/cf278e.html
Copyright © 2011-2022 走看看