CF487E & UOJ30:Tourists——题解

http://uoj.ac/problem/30

http://codeforces.com/problemset/problem/487/E

https://www.luogu.com.cn/problem/CF487E

(洛谷链接可以看中文题面)

(不会set的脑瘫患者在此)

题不是很难,圆方树先建起来,就不难想到用multiset维护每个方点为周围圆点权值最小值,然后跑一边树链剖分就好了。

但是每次修改圆点万一它旁边有一大堆方点暴力修改肯定会TLE。

所以我们只修改它的父亲方点,这样做的代价就是在查询$(x,y)$时如果$lca(x,y)$是方点那么不要忘了把它的父亲权值考虑在内。

码力下降太严重了

 

#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+5;
const int M=4e5+5;
const int INF=1e9; 
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct node{
    int u[M],v[M],nxt[M];
    int cnt,head[N];
    void init(){
        cnt=0;memset(head,0,sizeof(head));
    }
    void add(int U,int V){
        u[++cnt]=U;v[cnt]=V;nxt[cnt]=head[U];head[U]=cnt;
    }
}e,g;
int n,m,T,w[N];
int dfn[N],low[N],to[N],t,l;
stack<int>q;
void tarjan(int u,int f){
    dfn[u]=low[u]=++t;
    for(int i=g.head[u];i;i=g.nxt[i]){
        int v=g.v[i];
        if(!dfn[v]){
            q.push(i);tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]){
                int num;l++;
                do{
                    num=q.top();q.pop();
                    int x=g.u[num],y=g.v[num];
                    if(to[x]!=l){
                        to[x]=l;
                        e.add(x,l+n);e.add(l+n,x);
                    }
                    if(to[y]!=l){
                        to[y]=l;
                        e.add(y,l+n);e.add(l+n,y);
                    }
                }while(num!=i);
            }
        }else if(low[u]>dfn[v]&&f!=v){
            q.push(i);low[u]=dfn[v];
        }
    }
}
inline bool is_square(int x){
    return x>n;
}
multiset<int>minn[N];
int tot,fa[N],pos[N],idx[N],size[N],son[N],dep[N],top[N],val[N];
void dfs1(int u){
    size[u]=1;
    for(int i=e.head[u];i;i=e.nxt[i]){
        int v=e.v[i];
        if(fa[u]==v)continue;
        fa[v]=u;dep[v]=dep[u]+1;
        if(is_square(u))minn[u].insert(w[v]);
        dfs1(v);size[u]+=size[v];
        if(!son[u]||size[son[u]]<size[v])son[u]=v;
    }
}
void dfs2(int u,int anc){
    pos[u]=++tot;idx[tot]=u;top[u]=anc;
    if(!son[u])return;
    dfs2(son[u],anc);
    for(int i=e.head[u];i;i=e.nxt[i]){
        int v=e.v[i];
        if(v==fa[u]||v==son[u])continue;
        dfs2(v,v);
    }
}
inline void init(){
    dep[1]=1;
    dfs1(1);
    dfs2(1,1);
}
int tr[N<<2];
void build(int a,int l,int r){
    if(l==r){
        tr[a]=(is_square(idx[l]))? *minn[idx[l]].begin():w[idx[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(a<<1,l,mid);build(a<<1|1,mid+1,r);
    tr[a]=min(tr[a<<1],tr[a<<1|1]);
}
inline int query(int a,int l,int r,int l1,int r1){
    if(r1<l||l1>r)return INF;
    if(l1<=l&&r<=r1)return tr[a];
    int mid=(l+r)>>1;
    return min(query(a<<1,l,mid,l1,r1),query(a<<1|1,mid+1,r,l1,r1));
}
inline void modify(int a,int l,int r,int x){
    if(x<l||r<x)return;
    if(l==r){
        tr[a]=(is_square(idx[l]))? *minn[idx[l]].begin():w[idx[l]];
        return;
    }
    int mid=(l+r)>>1;
    modify(a<<1,l,mid,x);modify(a<<1|1,mid+1,r,x);
    tr[a]=min(tr[a<<1],tr[a<<1|1]);
}
inline int qry(int x,int y){
    int ans=INF;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ans=min(ans,query(1,1,n+l,pos[top[x]],pos[x]));
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    ans=min(ans,query(1,1,n+l,pos[x],pos[y]));
    return is_square(x)?min(ans,query(1,1,n+l,pos[fa[x]],pos[fa[x]])):ans;
}
inline void mdy(int x,int y){
    if(fa[x]){
        minn[fa[x]].insert(y);
        minn[fa[x]].erase(minn[fa[x]].find(w[x]));
        modify(1,1,n+l,pos[fa[x]]);
    }
    w[x]=y;
    modify(1,1,n+l,pos[x]);
}
int main(){
    n=read(),m=read(),T=read();
    for(int i=1;i<=n;i++)w[i]=read();
    for(int i=1;i<=m;i++){
        int u=read(),v=read();
        g.add(u,v);g.add(v,u);
    }
    tarjan(1,0);
    init();build(1,1,n+l);
    for(int i=1;i<=T;i++){
        char c=getchar();
        int x=read(),y=read();
        if(c=='C')mdy(x,y);
        if(c=='A')printf("%d\n",qry(x,y));
    }
    return 0;
}

 

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2020-02-06 17:17  luyouqi233  阅读(158)  评论(0编辑  收藏  举报