模拟赛T2 线段树优化建图+tarjan+拓扑排序

Posted guangheli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟赛T2 线段树优化建图+tarjan+拓扑排序相关的知识,希望对你有一定的参考价值。

然而这只是 70pts 的部分分,考场上没想到满分怎么做(现在也不会)  

code: 

#include <cstdio> 
#include <string>
#include <stack>  
#include <queue>    
#include <cstring>
#include <algorithm>  
#define N 100009 
#define lson ls[x] 
#define rson rs[x]  
#define inf 4500000   
using namespace std; 
void setIO(string s) {
    string in=s+".in"; 
    string out=s+".out"; 
    freopen(in.c_str(),"r",stdin); 
    freopen(out.c_str(),"w",stdout); 
}     
int scc;  
int cnt;   
int n;   
int tot;   
int edges;    
int A[N*5];   
int hd[N*5]; 
int to[N*30];   
int nex[N*30];   
int ls[N*5]; 
int rs[N*5];   
int vis[N*5];   
int dfn[N*5]; 
int low[N*5];  
int id[N*5];      
int In[N*5];  
int Ou[N*5];   
int tag[N*5];   
int X[N],L[N],R[N],con[N];
int is[N*5];             
stack<int>S;   
queue<int>q;    
vector<int>G[N*5];   
int newnode() { 
    return ++tot; 
}
void add(int u,int v) {
    // printf("%d %d
",u,v);   
    nex[++edges]=hd[u]; 
    hd[u]=edges; 
    to[edges]=v;    
}
void update(int &x,int l,int r,int p) {
    if(l==r) {
        x=p;   
        return;  
    }
    if(!x) {
        x=newnode(); 
    }
    int mid=(l+r)>>1;  
    if(X[p]<=mid) {
        update(lson,l,mid,p); 
    } 
    else {
        update(rson,mid+1,r,p); 
    }
}
void build(int x) {
    if(lson) {
        add(x,lson); 
        build(lson); 
    }
    if(rson) {
        add(x,rson); 
        build(rson); 
    }
}
void Add(int x,int l,int r,int L,int R,int rt) {
    if(!x) {
        return; 
    }
    if(l>=L&&r<=R) {
        add(rt,x); 
        return; 
    }
    int mid=(l+r)>>1;   
    if(L<=mid) {
        Add(lson,l,mid,L,R,rt); 
    }
    if(R>mid) {
        Add(rson,mid+1,r,L,R,rt); 
    }
}
void tarjan(int u) {        
    vis[u]=1;   
    S.push(u);  
    low[u]=dfn[u]=++cnt;   
    for(int i=hd[u];i;i=nex[i]) {
        int v=to[i];   
        if(!vis[v]) {
            tarjan(v);   
            low[u]=min(low[u],low[v]); 
        }
        else if(vis[v]==1) {
            low[u]=min(low[u],dfn[v]);    
        }
    }
    if(low[u]==dfn[u]) {
        ++scc;  
        for(;;) {
            int x=S.top(); 
            S.pop(); 
            id[x]=scc;     
            vis[x]=-1;    
            if(x==u) {
                break;  
            }
        }
    }
}
int main() {
    // setIO("broadcast"); 
    int i,j;  
    scanf("%d",&n); 
    tot=n;  
    int tp=0;  
    int root=0; 
    for(i=1;i<=n;++i) {
        scanf("%d%d",&X[i],&con[i]);    
        L[i]=X[i]-con[i]; 
        R[i]=X[i]+con[i];     
        A[++tp]=X[i];   
        A[++tp]=L[i]; 
        A[++tp]=R[i];        
    }      
    sort(A+1,A+1+tp); 
    for(i=1;i<=n;++i) {
        X[i]=lower_bound(A+1,A+1+tp,X[i])-A; 
        L[i]=lower_bound(A+1,A+1+tp,L[i])-A; 
        R[i]=lower_bound(A+1,A+1+tp,R[i])-A;  
    }      
    for(i=1;i<=n;++i) {
        update(root,1,inf,i);    
    }
    build(root);       
    for(i=1;i<=n;++i) {  
        Add(root,1,inf,L[i],R[i],i);   
    }   
    for(i=1;i<=n;++i) {
        if(!vis[i]) {
            tarjan(i);   
        }
    }                    
    for(i=1;i<=tot;++i) {
        for(j=hd[i];j;j=nex[j]) {
            int v=to[j];    
            if(!id[i]||!id[v]) {
                continue;   
            }                          
            if(id[v]!=id[i]) {
                ++In[id[v]];             
                ++Ou[id[i]];  
                G[id[i]].push_back(id[v]); 
            }
        }
    }
    for(i=1;i<=n;++i) {
        is[id[i]]=1;                
    }
    for(i=1;i<=scc;++i) {           
        if(!In[i]) {              
            q.push(i); 
        }
    }     
    while(!q.empty()) {    
        int u=q.front();                          
        q.pop();    
        for(int i=0;i<G[u].size();++i) {
            int v=G[u][i];      
            --In[v];   
            tag[v]|=(tag[u]|is[u]);    
            if(!In[v]) {            
                q.push(v);   
            }
        }       
    }    
    int a1=0; 
    int a2=0; 
    for(i=1;i<=scc;++i) {
        if(is[i]) {    
            ++a1;          
        }
    }
    for(i=1;i<=scc;++i) {
        if(!tag[i]&&is[i]) {
            ++a2; 
        }
    }
    printf("%d %d
",a2,a1);                               
    return 0;
}

  

以上是关于模拟赛T2 线段树优化建图+tarjan+拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj5017][Snoi2017]炸弹 tarjan缩点+线段树优化建图+拓扑

Nowcoder Hash Function ( 拓扑排序 && 线段树优化建图 )

[POI2015][bzoj4383] Pustynia [线段树优化建图+拓扑排序]

Codeforces1158 C. Permutation recovery(拓扑排序,线段树优化建图)

2019北京集训2duck 线段树优化建图+tarjan

线段树优化建图