BZOJ 2238: Mst DFS序+KDtree

明明可以用二维数点来做啊,网上为什么都是树剖+线段树呢 ?  

code: 

#include <cstdio> 
#include <cstring>   
#include <algorithm>   
#define N 100006 
#define inf 1000000
#define ll long long 
#define IO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)  
using namespace std;                     
namespace KD {    

    int d; 
    struct node { 
        int ch[2],p[2],mn[2],mx[2],Min,val;     
    }t[N];             

    bool cmp(node a,node b) 
    { 
        return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d];  
    }  

    int isin(int x1,int y1,int x2,int y2,int x) 
    {   
        if(t[x].mn[0]>=x1&&t[x].mx[0]<=y1&&t[x].mn[1]>=x2&&t[x].mx[1]<=y2)  
            return 1; 
        return 0; 
    } 

    int isout(int x1,int y1,int x2,int y2,int x) 
    {   
        if(x1>t[x].mx[0]||y1<t[x].mn[0]||x2>t[x].mx[1]||y2<t[x].mn[1])  
            return 1; 
        return 0; 
    }

    void pushup(int x,int y) 
    {   
        for(int i=0;i<2;++i) 
        {
            t[x].mn[i]=min(t[x].mn[i],t[y].mn[i]);   
            t[x].mx[i]=max(t[x].mx[i],t[y].mx[i]);  
        }
        t[x].Min=min(t[x].Min,t[y].Min);  
    }

    int build(int l,int r,int o) 
    {   
        d=o; 
        int mid=(l+r)>>1;    
        nth_element(t+l,t+mid,t+1+r,cmp);          
        t[mid].mn[0]=t[mid].mx[0]=t[mid].p[0]; 
        t[mid].mn[1]=t[mid].mx[1]=t[mid].p[1];      
        t[mid].Min=t[mid].val;    
        if(mid>l)     
        {
            t[mid].ch[0]=build(l,mid-1,o^1); 
            pushup(mid,t[mid].ch[0]); 
        }
        if(r>mid)  
        {
            t[mid].ch[1]=build(mid+1,r,o^1);   
            pushup(mid,t[mid].ch[1]); 
        }
        return mid;     
    } 

    int query(int x1,int y1,int x2,int y2,int x) 
    { 
        if(isout(x1,y1,x2,y2,x))  return inf;  
        if(isin(x1,y1,x2,y2,x))   return t[x].Min;      
        int re=inf;                 
        if(t[x].p[0]>=x1&&t[x].p[0]<=y1&&t[x].p[1]>=x2&&t[x].p[1]<=y2) 
        {
            re=min(re,t[x].val);    
        }     
        if(t[x].ch[0])   re=min(re,query(x1,y1,x2,y2,t[x].ch[0]));   
        if(t[x].ch[1])   re=min(re,query(x1,y1,x2,y2,t[x].ch[1]));    
        return re;  
    }

}; 
namespace T {   
    int p[N];  

    void init(int x) 
    { 
        for(int i=1;i<=x;++i) p[i]=i; 
    }    

    int find(int x) 
    {
        return p[x]==x?x:p[x]=find(p[x]); 
    }    

    int merge(int x,int y) 
    {
        x=find(x),y=find(y); 
        if(x!=y) 
        {
            p[x]=y;           
            return 1; 
        } 
        else return 0;     
    }

}; 

struct Edge {
    int x,y,c,id;     
    Edge(int x=0,int y=0,int c=0,int id=0):x(x),y(y),c(c),id(id){}  
    bool operator<(Edge a) const { return c<a.c; }            
}e[N];  
int n,m,edges,dfn;   
int hd[N],to[N<<1],nex[N<<1],val[N<<1],mk[N],fa[N],st[N],ed[N],go[N];   

void add(int u,int v,int c) 
{ 
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
}      

void dfs(int u,int ff) 
{  
    fa[u]=ff;       
    st[u]=++dfn; 
    for(int i=hd[u];i;i=nex[i]) 
    { 
        int v=to[i]; 
        if(v==ff)  continue;    
        dfs(v,u);      
    } 
    ed[u]=dfn; 
} 

int main() 
{   
    // IO("input"); 
    int i,j;   
    scanf("%d%d",&n,&m);   
    for(i=1;i<=m;++i) 
    {
        int x,y,z; 
        scanf("%d%d%d",&x,&y,&z);             
        e[i]=Edge(x,y,z,i);     
    }
    sort(e+1,e+1+m);            
    T::init(n);         
    ll ans=0;  
    int cn=0,tot=0;   
    for(i=1;i<=m;++i) 
    {    
        if(T::merge(e[i].x,e[i].y))          
        {
            ans+=(ll)e[i].c; 
            mk[e[i].id]=1,++cn; 
            add(e[i].x,e[i].y,e[i].c); 
            add(e[i].y,e[i].x,e[i].c);      
        }  
    }                             
    if(cn==n-1) dfs(1,0);  
    for(i=1;i<=m;++i) 
    {   
        go[e[i].id]=i;                  
        if(!mk[e[i].id]) 
        {   
            int x=e[i].x; 
            int y=e[i].y;        
            if(st[x]>st[y]) swap(x,y);  
            ++tot;              
            KD::t[tot].val=e[i].c;   
            KD::t[tot].p[0]=st[x];    
            KD::t[tot].p[1]=st[y];                      
        }
    }
    int root=KD::build(1,tot,0); 
    int q; 
    scanf("%d",&q);   
    for(i=1;i<=q;++i) 
    {
        int cur;  
        scanf("%d",&cur);                        
        if(cn<n-1)   printf("Not connected\n");  
        else 
        {     
            if(!mk[cur])   printf("%lld\n",ans);  
            else 
            { 
                cur=go[cur];                     
                int x=e[cur].x; 
                int y=e[cur].y;   
                if(fa[y]==x)  swap(x,y);    
                int re=inf;   
                if(st[x]>1)  
                { 
                    re=min(re,KD::query(1,st[x]-1,st[x],ed[x],root));     
                } 
                if(ed[x]<n)        
                {       
                    re=min(re,KD::query(st[x],ed[x],ed[x]+1,n,root));                
                }          
                if(re==inf)  printf("Not connected\n");  
                else printf("%lld\n",ans-e[cur].c+re);   
            }
        }
    }
    return 0; 
}   

  

posted @ 2019-12-24 18:55  EM-LGH  阅读(207)  评论(0编辑  收藏  举报