zoukankan      html  css  js  c++  java
  • BZOJ 1095: [ZJOI2007]Hide 捉迷藏 动态点分治+堆

    写了7k多,可以说是一己之力切掉了这道毒瘤题~

    开 $3$ 种堆,分别维护每个子树最大深度,以及每个节点在点分树中对父亲的贡献,和全局的最优解. 

    由于需要支持堆的删除,所以写起来特别恶心+麻烦. 

    细节巨多~

    #include <bits/stdc++.h> 
    #include <cstdio> 
    #include <queue> 
    #include <algorithm>  
    #define N 200004 
    #define setIO(s) freopen(s".in","r",stdin)  //  , freopen(s".out","w",stdout) 
    using namespace std;  
    int edges,n; 
    int hd[N],to[N<<1],nex[N<<1];     
    void add(int u,int v)
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
    }
    struct Queue
    { 
        priority_queue<int>q; 
        priority_queue<int>del;   
        void re() 
        {
            while(!q.empty()&&!del.empty()&&q.top()==del.top()) q.pop(),del.pop();
        }
        void pop() 
        {
            re();                  
            if(!q.empty()) q.pop();
        } 
        void push(int x) 
        {
            re();      
            q.push(x); 
        }  
        int empty() 
        {
            re(); 
            return q.empty(); 
        }
        int size() 
        {
            re(); 
            return q.size()-del.size();    
        }   
        int top() 
        { 
            re();   
            if(!q.empty()) 
                return q.top(); 
            else 
                return -1; 
        }   
        void erase(int x)
        {
            re();
            del.push(x);
        }   
    }F[N],G[N],Total; 
    namespace tree
    {  
        int dep[N],size[N],son[N],top[N],fa[N]; 
        void dfs1(int u,int ff)
        {
            fa[u]=ff,dep[u]=dep[ff]+1,size[u]=1; 
            for(int i=hd[u];i;i=nex[i]) 
                if(to[i]!=ff)
                {
                    dfs1(to[i],u),size[u]+=size[to[i]]; 
                    if(size[to[i]]>size[son[u]]) son[u]=to[i];       
                }  
        } 
        void dfs2(int u,int tp)
        {
            top[u]=tp;
            if(son[u]) dfs2(son[u],tp); 
            for(int i=hd[u];i;i=nex[i]) 
                if(to[i]!=fa[u]&&to[i]!=son[u]) 
                    dfs2(to[i],to[i]); 
        } 
        int LCA(int x,int y)
        {
            while(top[x]!=top[y]) 
                dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; 
            return dep[x]<dep[y]?x:y; 
        } 
        int Dis(int x,int y)
        {
            return dep[x]+dep[y]-(dep[LCA(x,y)]<<1);
        }
    };  
    int root,sn;
    int mx[N],vis[N],Fa[N],size[N],sta[N]; 
    void dfs(int u,int ff)
    {
        size[u]=1; 
        for(int i=hd[u];i;i=nex[i]) 
            if(to[i]!=ff&&!vis[to[i]]) 
                dfs(to[i],u),size[u]+=size[to[i]]; 
    }
    void getroot(int u,int ff)
    {   
        size[u]=1,mx[u]=0; 
        for(int i=hd[u];i;i=nex[i]) 
            if(!vis[to[i]]&&to[i]!=ff) 
                getroot(to[i],u),mx[u]=max(mx[u],size[to[i]]),size[u]+=size[to[i]]; 
        mx[u]=max(mx[u],sn-size[u]);  
        if(mx[u]<mx[root]) root=u; 
    }   
    void work(int u,int ff,int rt)
    { 
        if(Fa[rt]) 
            G[rt].push(tree::Dis(Fa[rt],u));    
        for(int i=hd[u];i;i=nex[i]) 
            if(to[i]!=ff&&!vis[to[i]]) 
                work(to[i],u,rt);        
    }  
    void calc(int u) 
    {   
        work(u,0,u);    
        F[u].push(0);     
        if(Fa[u]&&G[u].size()) F[Fa[u]].push(G[u].top());            
    }
    void prepare(int u) 
    {  
        vis[u]=1; 
        calc(u);       
        for(int i=hd[u];i;i=nex[i]) 
            if(!vis[to[i]]) 
                dfs(to[i],u),sn=size[to[i]],root=0,getroot(to[i],u),Fa[root]=u,prepare(root);       
        if(F[u].size()>=2) 
        {
            int a=0,b=0; 
            a=F[u].top(), F[u].pop();    
            b=F[u].top(), F[u].pop();               
            Total.push(a+b);          
            F[u].push(a), F[u].push(b);    
        }      
    } 
    // 开灯 (更小)                         
    void open(int u,int key) 
    { 
        int a=0,b=0,a1=0,b1=0; 
        if(F[u].size()>=2) 
        {
            a=F[u].top(),F[u].pop();     
            b=F[u].top(),F[u].pop();     
            F[u].push(a),F[u].push(b),F[u].erase(key);        
            if(F[u].size()>=2) 
            { 
                a1=F[u].top(),F[u].pop(); 
                b1=F[u].top(),F[u].pop();      
                F[u].push(a1),F[u].push(b1);     
                if(a1+b1!=a+b) 
                {
                    Total.erase(a+b); 
                    Total.push(a1+b1);    
                } 
            }
            else Total.erase(a+b); 
        }
        else F[u].erase(key); 
    } 
    void shut(int u,int key)
    { 
        int a=0,b=0,a1=0,b1=0; 
        if(F[u].size()>=1) 
        { 
            if(F[u].size()>=2) 
            { 
                a=F[u].top(),F[u].pop(); 
                b=F[u].top(),F[u].pop();     
                F[u].push(a),F[u].push(b),F[u].push(key);                       
                a1=F[u].top(),F[u].pop(); 
                b1=F[u].top(),F[u].pop();    
                F[u].push(a1),F[u].push(b1);        
                if(a1+b1!=a+b) 
                {
                    Total.erase(a+b);        
                    Total.push(a1+b1);    
                }
            } 
            else 
            {
                a=F[u].top(),F[u].push(key);    
                Total.push(a+key);    
            }
        }
        else F[u].push(key);          
    }
    // 开灯(更小)
    void update1(int u) 
    {   
        open(u,0);           
        for(int U=u;Fa[u];u=Fa[u]) 
        {     
            int dis=tree::Dis(U,Fa[u]); 
            if(G[u].top()==dis) 
            { 
                G[u].erase(dis);  
                open(Fa[u],dis);             
                if(!G[u].empty()) 
                { 
                    int a=G[u].top();
                    shut(Fa[u],a);  
                }
            }
            else G[u].erase(dis);         
        }
    }
    // 关灯(更大)
    void update2(int u) 
    { 
        shut(u,0);   
        for(int U=u;Fa[u];u=Fa[u]) 
        {
            int dis=tree::Dis(U,Fa[u]); 
            if(G[u].top()>=dis) G[u].push(dis);                      
            else if(G[u].empty()) 
            {
                G[u].push(dis); 
                shut(Fa[u],dis); 
            }
            else
            { 
                shut(Fa[u],dis);     
                open(Fa[u],G[u].top());         
                G[u].push(dis); 
            } 
        }
    } 
    int main()     
    { 
        int i,j,Q; 
        // setIO("input"); 
        scanf("%d",&n);  
        for(i=1;i<n;++i) 
        {
            int a,b; 
            scanf("%d%d",&a,&b),add(a,b),add(b,a); 
        } 
        tree::dfs1(1,0),tree::dfs2(1,1);      
        mx[0]=sn=n,root=0,getroot(1,0),prepare(root);      
        scanf("%d",&Q); 
        for(i=1;i<=Q;++i)        
        {
            char str[2]; 
            scanf("%s",str); 
            if(str[0]=='C') 
            {  
                int u; 
                scanf("%d",&u); 
                if(sta[u]==0) 
                {
                    update1(u); 
                }
                else 
                {
                    update2(u);     
                }
                sta[u]^=1;     
            }
            if(str[0]=='G') 
            { 
                if(Total.empty()) 
                    printf("-1
    ");                  
                else 
                    printf("%d
    ",Total.top());     
            }
        } 
    }
    

      

  • 相关阅读:
    状态模式
    策略模式Strategy(对象行为型)
    模板方法模式
    Java_观察者模式(Observable和Observer) -转
    Cordova自定义插件
    MongoVUE查询备忘
    C#关于HttpClient的统一配置(一)
    C#邮件收发
    WebApi统一输出接口
    移动开发兼容性问题及性能优化
  • 原文地址:https://www.cnblogs.com/guangheli/p/11454770.html
Copyright © 2011-2022 走看看