QTREE5 - Query on a tree V【题解】

前言

动点分。难度属于套路难度,只要掌握了模板,就会做。所以没有详细说明。

题面

;

sol

提醒的是,该题不需要建立tofa堆

代码

#include<bits/stdc++.h>
using namespace std;
const int _ = 1e5+1e3,INF = 2e9;
inline char gc(){
    static char buf[1<<6],*p1=buf,*p2=buf;
    return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<6,stdin),p1==p2)?EOF:*p1++;
}
template <class T>
inline void read(T&data){
    data=0;
    register char ch=0;
    while(ch<'0'||ch>'9')ch=gc();
    while(ch<='9'&&ch>='0'){
        data=(data<<3)+(data<<1)+(ch&15);
        ch=gc();
    }
    return;
}
namespace stringio{char Getchar(){register char ch=0;while(ch<'A'||ch>'Z')ch=gc();return ch;}}
using namespace stringio;

int n,m;
bool used[_];//零表示灭
struct heap{
    priority_queue<int,vector<int>,greater<int> >Q,del;
    void Delete(register int x){del.push(x);return;}
    void Push(register int x){Q.push(x);return;}
    void Clear(){while(!del.empty()&&del.top()==Q.top())Q.pop(),del.pop();return;}
    int Size(){Clear();return Q.size()-del.size();}
    int Get_fir(){Clear();if(Q.empty())return -1;else return Q.top();}
    int Get_sec(){
        if(Size()<2)return -1;
        register int x1 = Get_fir();Q.pop();
        register int x2 = Get_fir();Q.push(x1);
        return x2;
    }
    bool Empty(){Clear();return Q.empty();}
    int Get(){
        if(Size()<2)return -1;
        register int x1 = Get_fir(),x2 = Get_sec();
        return (x2 + x1);
    }
}c[_],b[_];
namespace Tree{
    int head[_],cnt,par[_],root;
    struct edge{
        int nt,to;
    }e[_];
    void add(register int a,register int b){e[++cnt].to=b,e[cnt].nt=head[a],head[a]=cnt;par[b]=a;return;}
}
class orginal_tree{
private:
    int head[_];
    struct edge{
        int nt,to;
    }e[_<<1];
    bool vis[_];
    int size[_],MX,all,lg[_<<1],st[18][_<<1],cnt,dfn[_],dis[_],fdfn[_],app[_],tot,root;
    void dfs(int now,int fa){
        dfn[now]=++cnt,fdfn[cnt]=now;st[0][++tot]=cnt,app[now]=tot;
        for(register int i=head[now];i;i=e[i].nt){
            if(e[i].to==fa)continue;
            dis[e[i].to]=dis[now]+1;
            dfs(e[i].to,now);
            st[0][++tot]=dfn[now];
        }
    }
    int get_lca(register int u,register int v){
        u=app[u],v=app[v];
        if(u<v)swap(u,v);register int LEN=lg[u-v+1];
        return fdfn[min(st[LEN][v],st[LEN][u+1-(1<<LEN)])];
    }
    void getroot(register int now,register int fa){
        size[now]=1;
        int mx=0;
        for(register int i=head[now];i;i=e[i].nt)
        {
            if(vis[e[i].to]||e[i].to==fa)continue;
            getroot(e[i].to,now);
            size[now]+=size[e[i].to];
            mx=mx<size[e[i].to]?size[e[i].to]:mx;
        }
        mx=mx<all-size[now]?all-size[now]:mx;
        if(MX>mx)MX=mx,root=now;
    }
    void p_divide(int now){
        vis[now]=1;
        for(register int i=head[now];i;i=e[i].nt){
            if(vis[e[i].to])continue;
            MX=INF,all=size[e[i].to];
            getroot(e[i].to,0);
            Tree::add(now,root);
            p_divide(root);
        }
    }
public:
    void add(register int a,register int b){e[++cnt].to=a,e[cnt].nt=head[b],head[b]=cnt;}
    void Add(){for(register int i=1,a,b;i<n;++i)read(a),read(b),add(a,b),add(b,a);}
    void init(){
        Add();
        MX=INF,all=n;
        cnt=0;dfs(1,0);getroot(1,0);
        register int us=2*n-1;
        for(register int i=2;i<=us;++i)lg[i]=lg[i>>1]+1;
        for(register int j=1;j<=17;++j)
            for(register int i=1;i<=us&&(i+(1<<(j-1)))<=us;++i)
                st[j][i]=min(st[j-1][i],st[j-1][i+(1<<(j-1))]);
        Tree::root=root;
        p_divide(root);
    }
    int getdist(register int u,register int v){
        return dis[u]+dis[v]-2*dis[get_lca(u,v)];
    }
}tr;
namespace Tree{
    void insert(register int now){
        used[now]=1;
        c[now].Push(0);
        for(register int i=par[now];i;i=par[i]){
            c[i].Push(tr.getdist(now,i));
        }
    }
    void erase(register int now){
        used[now]=0;
        c[now].Delete(0);
        for(register int i=par[now];i;i=par[i]){
            c[i].Delete(tr.getdist(now,i));
        }
    }
    void init(){
        for(register int i=1;i<=n;++i)
            insert(i) ;     
    }
    int query(register int now){
        register int MMMXX=2e9;
        for(register int i=now;i;i=par[i]){
            register int ddd=tr.getdist(i,now);
            register int ans=c[i].Get_fir();
            if(ans==-1)continue;
            else MMMXX=min(MMMXX,ans+ddd);
        }
        if(MMMXX==2e9)return -1;
        return MMMXX;
    }
}
int main(){
    read(n);
    tr.init();
    //Tree::init();
    read(m);
    while(m--){
        register  int ki;read(ki);
        register int fdfdf;read(fdfdf);
        if(ki==1){
            printf("%d\n",Tree::query(fdfdf));
        }
        else {
            used[fdfdf]?Tree::erase(fdfdf):Tree::insert(fdfdf);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/JH_2002/article/details/81353622