zoukankan      html  css  js  c++  java
  • uoj#30 Tourist (圆方树学习笔记)

    WC陈俊锟课件

    学会了可删除堆

     例题1 : 求图中两点间路径上最大(最小)权值

    无修改
    设圆点权值为本身,方点权值为点双中的最大(小)权值
    查询链上最大值
    并查集??

    有修改

    设圆点权值为本身,方点权值为点双中非根节点的最大(小)权值

    修改时修改父方点的权值(堆维护)

    注意: 查询时如果LCA是方点,还要考虑方点的父圆点的权值

    uoj#30

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 200010;
    const int INF = 2e9+7;
    
    int n,m,qq;
    int w[maxn];
    char op[10];
    
    int h[maxn],size,h1[maxn],size1;
    struct E{
        int to,next;
    }e[maxn<<1],e1[maxn<<1];
    void add(int u,int v){
        e[++size].to=v;
        e[size].next=h[u];
        h[u]=size;
    }
    void add1(int u,int v){
        e1[++size1].to=v;
        e1[size1].next=h1[u];
        h1[u]=size1;
    }
    
    struct Set{ // 可删除堆 
        priority_queue<int,vector<int>,greater<int> > q1,q2;
        void insert(int x) { q1.push(x); }
        void erase(int x){ q2.push(x); }
        int top(){
            while((!q2.empty())&&(q1.top()==q2.top())){ q1.pop(); q2.pop(); }
            return q1.top();
        }
    }q[maxn];
    
    struct Node{
        int mn;
    }t[maxn<<2];
    
    int fa[maxn],sz[maxn],son[maxn],top[maxn],dep[maxn],id[maxn];
    
    int dfn[maxn],low[maxn],tim,tot,sta[maxn],topp;
    
    void tarjan(int u){
        dfn[u]=low[u]=++tim; sta[++topp]=u;
        for(int i=h[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
                if(low[v]>=dfn[u]){
                    ++tot;
                    add1(u,tot),add1(tot,u);
                    int x=0;
                    do{
                        x=sta[topp--];
                        add1(x,tot),add1(tot,x);
                    }while(x!=v);
                }
            }
            else low[u]=min(low[u],dfn[v]);
        }
    }
    
    void dfs1(int u,int par){
        sz[u]=1; fa[u]=par; dep[u]=dep[par]+1;
        if(u<=n&&par) q[par].insert(w[u]); // 更新方点权值 
        
        int maxson=-1;
        for(int i=h1[u];i!=-1;i=e1[i].next){
            int v=e1[i].to;
            if(v==par) continue;
            dfs1(v,u);
            sz[u]+=sz[v];
            if(maxson<sz[v]){
                maxson=sz[v];
                son[u]=v;
            }
        }
    }
    
    void dfs2(int u,int par){
        dfn[u]=++tim;
        id[tim]=u;
        top[u]=par;
        
        if(!son[u]) return;
        dfs2(son[u],par);
        for(int i=h1[u];i!=-1;i=e1[i].next){
            int v=e1[i].to;
            if(v==fa[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
    
    void pushup(int i){
        t[i].mn=min(t[i<<1].mn,t[i<<1|1].mn);
    }
    
    void update(int i,int k,int l,int r,int p){
        if(l==r){
            t[i].mn=k;
            return;
        }
        int mid=(l+r)/2;
        if(p<=mid) update(i<<1,k,l,mid,p);
        else update(i<<1|1,k,mid+1,r,p);
        pushup(i);
    }
    
    int query(int i,int l,int r,int x,int y){
        if(x<=l&&r<=y){
            return t[i].mn;
        }
        int mid=(l+r)/2;
        if(y<=mid) return query(i<<1,l,mid,x,y);
        if(x>mid) return query(i<<1|1,mid+1,r,x,y);
        return min(query(i<<1,l,mid,x,y),query(i<<1|1,mid+1,r,x,y));
    }
    
    int qry(int u,int v){
        int res=INF;
        while(top[u]^top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            res=min(res,query(1,1,tot,dfn[top[u]],dfn[u]));
            u=fa[top[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        res=min(res,query(1,1,tot,dfn[u],dfn[v]));
        if(u>n) res=min(res,w[fa[u]]); // 如果LCA是方点,还要考虑其父节点的贡献 
        return res;
    }
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}
    
    int main(){
        memset(h,-1,sizeof(h));
        memset(h1,-1,sizeof(h1));
        n=read(),m=read(),qq=read();
        for(int i=1;i<=n;i++) w[i]=read();
        int u,v;
        for(int i=1;i<=m;i++){
            u=read(),v=read();
            add(u,v),add(v,u);
        }
        
        tot=n;
        for(int i=1;i<=n;i++){
            if(!dfn[i]) tarjan(i);
        }
        
        tim=0; dfs1(1,0); dfs2(1,1);
        
        for(int i=1;i<=n;i++) update(1,w[i],1,tot,dfn[i]);
        for(int i=n+1;i<=tot;i++) update(1,q[i].top(),1,tot,dfn[i]);
        
        for(int i=1;i<=qq;i++){
            scanf("%s",op); u=read(),v=read();
            if(op[0]=='C'){ // 每个方点维护的信息是点双内非根节点的最小值
                if(fa[u]) q[fa[u]].erase(w[u]);
                w[u]=v;
                update(1,w[u],1,tot,dfn[u]);
                if(fa[u]){ 
                    q[fa[u]].insert(w[u]);
                    update(1,q[fa[u]].top(),1,tot,dfn[fa[u]]);
                }
            }else{
                printf("%d\n",qry(u,v));
            }
        }
        return 0;
    }
    View Code

    例题2: 

  • 相关阅读:
    排序算法之希尔排序
    javascript Set data structures
    javascript Dictionary data structures
    javascript linkedlist data structures
    关于Java Collections的几个常见问题
    java NIO中的buffer和channel
    编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。如:ABCABCABC…… 依次递归
    Java多线程之Callable接口的实现
    Java并发:volatile内存可见性和指令重排
    Lock和synchronized的区别和使用
  • 原文地址:https://www.cnblogs.com/tuchen/p/10404763.html
Copyright © 2011-2022 走看看