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: 

原文地址:https://www.cnblogs.com/tuchen/p/10404763.html