[bzoj1095][ZJOI2007]Hide 捉迷藏(动态点分治)

传送门
话说我明明是抄的po姐的代码,为什么我的23s,po姐的14s???
看来我代码已经很接近颜值了。。
其实这题就是维护好多个堆,每个点两个,再来一个全局堆就好了。
具体还是看po姐的blog吧:
http://blog.csdn.net/popoqqq/article/details/44461423
代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
inline int read(){
    int x=0;char ch=' ';int f=1;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int N=1e5+5;
struct Priority_Queue{
    priority_queue<int> heap,del;
    void push(int x){
        heap.push(x);
    }
    void erase(int x){
        del.push(x);
    }
    void pop(){
        while(del.size()&&heap.top()==del.top())
            heap.pop(),del.pop();
        heap.pop();
    }
    int top(){
        while( del.size() && heap.top()==del.top() )
            heap.pop(),del.pop();
        return heap.top();
    }
    int second_top(){
        int temp=top();pop();
        int re=top();push(temp);
        return re;
    }
    int size(){
        return heap.size()-del.size();
    }
}h1[N],h2[N],all;
struct edge{
    int to,next;
}e[N<<1];
int n,q,nowsize,tot;
int can[N],size[N];
int head[N];
inline void addedge(int x,int y){
    e[++tot].to=y;e[tot].next=head[x];head[x]=tot;
}
inline void Insert(Priority_Queue &s){
    if(s.size()>=2){
        all.push(s.top()+s.second_top());
    }
}
inline void Erase(Priority_Queue &s){
    if(s.size()>=2){
        all.erase(s.top()+s.second_top());
    }
}
int dep[N],f[N];
int father[N],vis[N];
int st[17][N];
inline void dfs(int x,int fa){
    dep[x]=dep[fa]+1;
    size[x]=1;
    st[0][x]=fa;
    for(int k=1;k<=16&&(1<<k)<=dep[x];k++){
        st[k][x]=st[k-1][st[k-1][x]];
    }
    for(int i=head[x];i;i=e[i].next){
        int u=e[i].to;
        if(u==fa)continue;
        dfs(u,x);
        size[x]+=size[u];
    }
}
inline int getlca(int x,int y){
    if(x==y)return x;
    if(dep[x]>dep[y])swap(x,y);
    for(int k=16;k>=0;k--){
        if(dep[st[k][y]]>=dep[x]){
            y=st[k][y];
        }
    }
    if(x==y)return x;
    for(int k=16;k>=0;k--){
        if(st[k][x]!=st[k][y]){
            x=st[k][x];
            y=st[k][y];
        }
    }
    return st[0][x];
}
inline int getsize(int x,int fa){
    int res=1;
    for(int i=head[x];i;i=e[i].next){
        int u=e[i].to;
        if(u==fa||vis[u])continue;
        res+=getsize(u,x);
    }
    return res;
}
inline void getroot(int x,int fa,int &root){
    size[x]=1;f[x]=0;
    for(int i=head[x];i;i=e[i].next){
        int u=e[i].to;
        if(u==fa)continue;
        if(vis[u])continue;
        getroot(u,x,root);
        size[x]+=size[u];
        f[x]=max(f[x],size[u]);
    }
    f[x]=max(f[x],nowsize-size[x]);
    if(f[x]<f[root])root=x;
}
inline void getdis(int x,int fa,int root,int dis,Priority_Queue &s){
    s.push(dis+1);
    for(int i=head[x];i;i=e[i].next){
        int u=e[i].to;
        if(u==fa)continue;
        if(vis[u])continue;
        getdis(u,x,root,dis+1,s);
    }
}
inline int build(int x){
    int root=0;f[0]=0x3f3f3f3f;
    nowsize=getsize(x,0);
    getroot(x,0,root);
    h2[root].push(0);
    vis[root]=1;
    for(int i=head[root];i;i=e[i].next){
        int u=e[i].to;
        if(vis[u])continue;
        Priority_Queue s;
        getdis(u,root,root,0,s);
        int tmp=build(u);
        father[tmp]=root;h1[tmp]=s;
        h2[root].push(h1[tmp].top());
    }
    Insert(h2[root]);
    return root;
}
inline int disxy(int x,int y){
    int lca=getlca(x,y);
    return dep[x]+dep[y]-dep[lca]*2;
}
inline void turn_on(int x){
    Erase(h2[x]);
    h2[x].push(0);
    Insert(h2[x]);
    for(int i=x;father[i];i=father[i]){
        Erase(h2[father[i]]);
        if(h1[i].size()){
            h2[father[i]].erase(h1[i].top());
        }
        h1[i].push(disxy(father[i],x));
        if(h1[i].size()){
            h2[father[i]].push(h1[i].top());
        }
        Insert(h2[father[i]]);
    }
}
inline void turn_off(int x){
    Erase(h2[x]);
    h2[x].erase(0);
    Insert(h2[x]);
    for(int i=x;father[i];i=father[i]){
        Erase(h2[father[i]]);
        if(h1[i].size()){
            h2[father[i]].erase(h1[i].top());
        }
        h1[i].erase(disxy(father[i],x));
        if(h1[i].size()){
            h2[father[i]].push(h1[i].top());
        }
        Insert(h2[father[i]]);
    }
}
int main(){
    n=read();
    for(int i=1;i<n;i++){
        int x=read(),y=read();
        addedge(x,y);addedge(y,x);
    }
    dfs(1,0);
    build(1);
    q=read();
    for(int i=1;i<=n;i++){
        can[i]=0;
    }
    int now=0;
    while(q--){
        char ch[3];
        scanf("%s",ch);
        if(ch[0]=='G'){
            if(now==n)printf("-1");
            else printf("%d\n",all.top());
        }
        else{
            int x=read();
            if(can[x]){
                now--;
                can[x]=0;
                turn_on(x);
            }
            else{
                now++;
                can[x]=1;
                turn_off(x);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值