zoukankan      html  css  js  c++  java
  • CF487E Tourists(园方树+树链剖分)

    园方树+树链剖分

    这题首先容易得到的性质是,一个点双内的所有点互相到达,这就说明这个点双的答案就是他们中的最小值,因此建立园方树。方点就维护了最值

    现在有修改问题,对于一个圆点的修改,势必要影响到方点,我们对每个方点维护一个multiset,这样对于每个圆点的修改,都是对他的父亲方点进行修改,这样可以维护单点权值

    那么查询的时候,因为是一段路径,因此考虑树链剖分后查询,唯一有一个特殊点就是,当他们的lca是方点,那么这个方点的父亲圆点信息也可能影响方案,这里注意一下即可。

    这道题算法比较明显,就是模板多。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=4e5+10;
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    int h[N],e[N],ne[N],idx;
    int dfn[N],ins[N],low[N],w[N],times;
    int depth[N],fa[N],id[N],top[N],son[N],sz[N];
    stack<int> st;
    vector<int> g[N];
    multiset<int> m1[N];
    int vis[N];
    int cnt;
    int n,m;
    struct node{
        int l,r;
        ll mi;
    }tr[N<<2];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void tarjan(int u){
        ins[u]=1;
        dfn[u]=low[u]=++times;
        int i;
        st.push(u);
        for(int i=h[u];i!=-1;i=ne[i]){
            int v=e[i];
            if(!dfn[v]){
                fa[v]=u;
                tarjan(v);
                low[u]=min(low[u], low[v]);
                if(dfn[u]<=low[v]){
                    ++cnt;
                    while(1){
                        auto x=st.top();
                        g[cnt].push_back(x);
                        g[x].push_back(cnt);
                        ins[x]=0; st.pop();
                        if(x==v) break;
                    }
                    g[cnt].push_back(u);
                    g[u].push_back(cnt);
                }
            }
            else if(v!=fa[u]){
                low[u]=min(low[u], dfn[v]);
            }
        }
    }
    void dfs1(int u,int ff){
        int i;
        sz[u]=1;
        vis[u]=1;
        for(i=0;i<(int)g[u].size();i++){
            int j=g[u][i];
            if(vis[j])
                continue;
            depth[j]=depth[u]+1;
            fa[j]=u;
            dfs1(j,u);
            sz[u]+=sz[j];
            if(sz[j]>sz[son[u]]){
                son[u]=j;
            }
        }
    }
    void dfs2(int u,int x){
        vis[u]=1;
        top[u]=x;
        dfn[u]=++times;
        id[times]=u;
        if(!son[u])
            return ;
        dfs2(son[u],x);
        int i;
        for(i=0;i<(int)g[u].size();i++){
            int j=g[u][i];
            if(vis[j])
                continue;
            dfs2(j,j);
        }
    }
    void pushup(int u){
        tr[u].mi=min(tr[u<<1].mi,tr[u<<1|1].mi);
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]={l,r,w[id[l]]};
        }
        else{
            tr[u]={l,r};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
            pushup(u);
        }
    }
    void modify(int u,int l,int x){
        if(tr[u].l==tr[u].r){
            tr[u].mi=x;
            return ;
        }
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)
            modify(u<<1,l,x);
        else
            modify(u<<1|1,l,x);
        pushup(u);
    }
    int query(int u,int l,int r){
        if(tr[u].l>=l&&tr[u].r<=r){
            return tr[u].mi;
        }
        int mid=tr[u].r+tr[u].l>>1;
        int res=inf;
        if(l<=mid)
            res=query(u<<1,l,r);
        if(r>mid)
            res=min(res,query(u<<1|1,l,r));
        return res;
    }
    int pathquery(int x,int y){
        int res=inf;
        while(top[x]!=top[y]){
            if(depth[top[x]]<depth[top[y]])
                swap(x,y);
            res=min(res,query(1,dfn[top[x]],dfn[x]));
            x=fa[top[x]];
        }
        if(depth[x]>depth[y])
            swap(x,y);
        res=min(res,query(1,dfn[x],dfn[y]));
        if(x>n){
            res=min(res,w[fa[x]]);
        }
        return res;
    }
    int main(){
        ios::sync_with_stdio(false);
        int i,j,q;
        cin>>n>>m>>q;
        memset(h,-1,sizeof h);
        cnt=n;
        for(i=1;i<=n;i++)
            cin>>w[i];
        for(i=1;i<=m;i++){
            int a,b;
            cin>>a>>b;
            add(a,b);
            add(b,a);
        }
        tarjan(1);
        times=0;
        depth[1]=1;
        dfs1(1,0);
        memset(vis,0,sizeof vis);
        dfs2(1,1);
        for(i=2;i<=n;i++){
            m1[fa[i]-n].insert(w[i]);
        }
        for(i=n+1;i<=cnt;i++){
            w[i]=(m1[i-n].empty())?inf:*m1[i-n].begin();
        }
        build(1,1,cnt);
        while(q--){
            string opt;
            cin>>opt;
            if(opt=="C"){
                int x,tmp;
                cin>>x>>tmp;
                modify(1,dfn[x],tmp);
                if(x==1){
                    w[x]=tmp;
                    continue;
                }
                m1[fa[x]-n].erase(m1[fa[x]-n].lower_bound(w[x]));
                m1[fa[x]-n].insert(tmp);
                w[x]=tmp;
                if(*m1[fa[x]-n].begin()==w[fa[x]]){
                    continue;
                }
                int pos=*m1[fa[x]-n].begin();
                w[fa[x]]=pos;
                modify(1,dfn[fa[x]],pos);
            }
            else{
                int a,b;
                cin>>a>>b;
                cout<<pathquery(a,b)<<endl;
            }
        }
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    OpenCV在MFC图像控件内显示图像
    Android APK反编译具体解释(附图)
    Android下用Properties保存程序配置
    王灏:光音网络致力打造Wi-Fi大生态圈
    解决ccSvcHst.exe CPU占用超50%的问题,及其缘由
    配置管理工具比較
    应用程序无法正常启动0xc0150002 解决方式
    现有一些开源ESB总线的比較
    使用GridView自带分页的代码
    Hadoop 2.4.0新特性介绍
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13972989.html
Copyright © 2011-2022 走看看