zoukankan      html  css  js  c++  java
  • [并查集][Tarjan] Bzoj P5017 炸弹

    Description

    在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: 
    Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆。 
    现在,请你帮忙计算一下,先把第 i 个炸弹引爆,将引爆多少个炸弹呢? 

    Input

    第一行,一个数字 N,表示炸弹个数。 
    第 2∼N+1行,每行 2 个数字,表示 Xi,Ri,保证 Xi 严格递增。 
    N≤500000
    −10^18≤Xi≤10^18
    0≤Ri≤2×10^18

    Output

    一个数字,表示Sigma(i*炸弹i能引爆的炸弹个数),1<=i<=N mod10^9+7。 

    Sample Input

    4
    1 1
    5 1
    6 5
    15 15

    Sample Output

    32
     
     

    题解

    • 这题我们可以选择用并查集来做
    • 对于一个炸弹i,如果它的爆炸范围能到达另一个炸弹,那么炸弹i所能爆炸的范围就是两个炸弹左区间取min,右区间取max的

    • 那我们就先处理出当前点并到所能到达的最远点
    • 然后就进行tarjan缩点,就会缩成一个DAG,答案就是DAG中的可到达的点数
    • 考虑怎么做?然后我们会发现对于取的点一定是在一段连续的区间内
    • 然后就用并查集维护size就好了

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #define ll long long
     7 using namespace std;
     8 const int N=5e5+10,mo=1e9+7;
     9 ll ans;
    10 int n,cnt,num,tot,top,fa[N],head[N],last[N],bel[N],size[N],val[N],dfn[N],low[N],vis[N],stack[N];
    11 struct node {ll x,r;} b[N];
    12 struct edge {int from,to;}e[N*4],E[N*4];
    13 void insert(int x,int y) { e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt; }
    14 void ins(int x,int y) { E[++tot].to=y,E[tot].from=last[x],last[x]=tot; }
    15 int getfather(int x) { return fa[x]==x?x:fa[x]=getfather(fa[x]); }
    16 void tarjan(int x)
    17 {
    18     dfn[x]=low[x]=++dfn[0],stack[++top]=x,vis[x]=1;
    19     for (int i=head[x];i;i=e[i].from)
    20         if (!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]); else if (vis[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
    21     if (dfn[x]==low[x])
    22     {
    23         int p=0; num++;
    24         while (p!=x) p=stack[top--],vis[p]=0,bel[p]=num,++size[num],val[num]=(val[num]+p)%mo;
    25     }
    26 }
    27 void count(int x)
    28 {
    29     if (vis[x]) return;
    30     for (int i=last[x];i;i=E[i].from)
    31     {
    32         int u=getfather(x),v=getfather(E[i].to);
    33         if (u^v) fa[v]=u,size[u]+=size[v];
    34     }
    35     vis[x]=1;
    36 }
    37 int main()
    38 {
    39     scanf("%d",&n);
    40     for (int i=1;i<=n;i++) scanf("%lld%lld",&b[i].x,&b[i].r);
    41     for (int i=1;i<=n;i++) fa[i]=i;
    42     for (int i=2;i<=n;i++)
    43     {
    44         int p=i-1;
    45         while (p) if (b[i].x-b[i].r<=b[p].x) insert(i,p),fa[getfather(i)]=getfather(p),p=getfather(i)-1; else break;
    46     }
    47     for (int i=1;i<=n;i++) fa[i]=i;
    48     for (int i=n-1;i;i--)
    49     {
    50         int p=i+1;
    51         while (p<=n) if (b[i].x+b[i].r>=b[p].x) insert(i,p),fa[getfather(i)]=getfather(p),p=getfather(i)+1; else break;
    52     }
    53     for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
    54     for (int u=1;u<=n;u++) for (int i=head[u];i;i=e[i].from) if (bel[u]!=bel[e[i].to]) ins(bel[u],bel[e[i].to]);
    55     for (int i=1;i<=num;i++) fa[i]=i;
    56     for (int i=1;i<=num;i++) count(i),ans=(ans+1ll*val[i]*size[i]%mo)%mo;
    57     printf("%lld",ans);
    58 }
  • 相关阅读:
    数据分析也有发展趋势
    数据分析也有发展趋势
    大数据与人的主体性
    大数据与人的主体性
    数据分析告诉我们的四个经验教训
    数据分析告诉我们的四个经验教训
    大数据新闻传播是什么
    数据分析告诉你,转化才是王道
    数据分析告诉你,转化才是王道
    企业应如何培养数据驱动的分析文化?
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11143914.html
Copyright © 2011-2022 走看看