[SNOI2017] Bomb (Line segment tree optimization drawing)

[SNOI2017] Bomb (luogu)

Solution

  • This question can direct a bomb to a bomb it can detonate with a directed edge
  • Then search for the number of bombs that a bomb can reach along the directed edge in the built graph
  • It seems that it can be optimized with the contraction point of the strong Unicom component?

Since the bomb that each bomb can detonate must be a continuous section, you can record which section of bomb represents each retracted point when retracting

After shrinking the point, dfs again finds out which segment can be detonated

But the person who made the question is too malicious and needs to connect n 2 sides. . .

Since the connected edges are always a range, we consider whether we can use line tree optimization

Build a line segment tree with n leaf nodes (the father connects to the son with an order of magnitude n), and use each bomb as the leaf node corresponding to the number

Then connect the edges to the corresponding line segment when connecting the edges, the total number of connected edges is within the order of nlogn

Code

 

#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <algorithm>
#define ll long long
#define mid ((l+r)>>1)
#define lc (g<<1)
#define rc ((g<<1)|1)
using namespace std;
const int N=5e5+10,M=2e6+10,P=1e9+7;
vector <int> link[M],son[M],re[M];
int n,id[N],scc,d[M],le[M],ri[M],m;
int top,dfn[M],low[M],tot,st[M],in[M],ans;
ll x[N],r[N];
struct node
{
    int l,r;
    inline node(int l=0,int r=0):l(l),r(r){};
}f[M];
void build(int g,int l,int r)
{
    f[g]=node(l,r);
    m=max(m,g);
    if(l==r)
    {
        id[l]=g;
        return;
    }
    link[g].push_back(lc);
    link[g].push_back(rc);
    build(lc,l,mid);
    build(rc,mid+1,r);
}
void add(int g,int l,int r,int ul,int ur,int v)
{
    if(ul<=l && r<=ur)
    {
        link[v].push_back(g);
        return;
    }
    if(ur<=mid) add(lc,l,mid,ul,ur,v);
    else if(ul>mid) add(rc,mid+1,r,ul,ur,v);
    else add(lc,l,mid,ul,mid,v),add(rc,mid+1,r,mid+1,ur,v);
}
void tarjan(int u)
{
    dfn[u]=low[u]=++tot;
    st[++top]=u,in[u]=1;
    int size=link[u].size();
    for(int i=0;i<size;i++)
    {
        int v=link[u][i];
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(in[v]) low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        scc++;
        int z=0;
        do
        {
            z=st[top--];
            d[z]=scc,in[z]=0;
            le[scc]=min(le[scc],f[z].l);
            ri[scc]=max(ri[scc],f[z].r);
        }while(z!=u);
    }
}
void dfs(int u)
{
    in[u]=1;
    int size=re[u].size();
    for(int i=0;i<size;i++)
    {
        int v=re[u][i];
        if(!in[v]) dfs(v);
        le[u]=min(le[u],le[v]);
        ri[u]=max(ri[u],ri[v]);
    }
}
int query(int x)
{ 
    int u=d[id[x]];
    return ri[u]-le[u]+1;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld%lld",&x[i],&r[i]);
    build(1,1,n);
    for(int i=1;i<=n;i++)
    {
        int L=lower_bound(x+1,x+1+n,x[i]-r[i])-x;
        int R=upper_bound(x+1,x+1+n,x[i]+r[i])-x-1;
        add(1,1,n,L,R,id[i]);
    }
    memset(le,0x3f,sizeof(le));
    tarjan(1);
    for(int u=1;u<=m;u++)
    {
        int size=link[u].size();
        for(int i=0,v;i<size;i++)
            if(d[v=link[u][i]]!=d[u])
                re[d[u]].push_back(d[v]);
    }
    dfs(d[1]);
    for(int i=1;i<=n;i++) ans=(ans+(ll)query(i)*i%P)%P;
    printf("%d",ans);
    return 0;
}

 

 

 

Guess you like

Origin www.cnblogs.com/hsez-cyx/p/12723857.html