• BZOJ5017 炸弹(线段树优化建图+Tarjan+拓扑)


    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。

    题解

    因为每一个炸弹爆炸后引爆的是一个区间的炸弹,所以想到线段树优化建图。

    然后可能有环所以跑Tarjan求强连通分量。最后拓扑合并答案。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 const int N=500010;
      9 const int mod=1e9+7;
     10 queue<int> q;
     11 int cnt,cnt1,head[N*4],head1[N*4];
     12 int num,id[N*4],di[N*4];
     13 int dfn[N*4],low[N*4],tot1,top,stack[N*4],book[N*4],num1,col[N*4],tmp;
     14 long long a[N],r[N],b[N],maxx[N*4],minn[N*4];
     15 int n,tot,in[N*4];
     16 long long ans;
     17 struct tree{
     18     int l,r;
     19 }tr[N*4];
     20 struct edge{
     21     int to,nxt,u;
     22 }e[N*20],e1[N*20];
     23 void add(int u,int v){
     24     cnt++;
     25     e[cnt].nxt=head[u];
     26     e[cnt].u=u;
     27     e[cnt].to=v;
     28     head[u]=cnt;
     29 }
     30 void add1(int u,int v){
     31     cnt1++;
     32     e1[cnt1].nxt=head1[u];
     33     e1[cnt1].to=v;
     34     head1[u]=cnt1;
     35 }
     36 void build(int l,int r,int now){
     37     num=max(num,now);
     38     tr[now].l=l;tr[now].r=r;
     39     if(r==l){
     40         id[l]=now;
     41         di[now]=l;
     42         return;
     43     }
     44     int mid=(tr[now].l+tr[now].r)>>1;
     45     build(l,mid,now*2);
     46     build(mid+1,r,now*2+1);
     47     add(now,now*2);
     48     add(now,now*2+1);
     49 }
     50 void update(int l,int r,int now,int u){
     51     if(tr[now].l==l&&tr[now].r==r){
     52         add(u,now);
     53         return;
     54     }
     55     int mid=(tr[now].l+tr[now].r)>>1;
     56     if(l>mid)update(l,r,now*2+1,u);
     57     else if(r<=mid)update(l,r,now*2,u);
     58     else{
     59         update(l,mid,now*2,u);
     60         update(mid+1,r,now*2+1,u);
     61     }
     62 }
     63 void Tarjan(int u){
     64     dfn[u]=low[u]=++tot1;
     65     stack[++top]=u;
     66     book[u]=1;
     67     for(int i=head[u];i;i=e[i].nxt){
     68         int v=e[i].to;
     69         if(dfn[v]==0){
     70             Tarjan(v);
     71             low[u]=min(low[u],low[v]);
     72         }
     73         else if(book[v])low[u]=min(low[u],dfn[v]);
     74     }
     75     if(dfn[u]==low[u]){
     76         int x;
     77         num1++;
     78         minn[num1]=4e18;
     79         maxx[num1]=-4e18;
     80         bool flag=false;
     81         do{
     82             x=stack[top--];
     83             book[x]=0;
     84             col[x]=num1;
     85             if(di[x]){
     86                 if(!flag){
     87                     minn[num1]=a[di[x]]-r[di[x]];
     88                     maxx[num1]=a[di[x]]+r[di[x]];
     89                     flag=true;
     90                 }
     91                 else{
     92                     minn[num1]=min(minn[num1],a[di[x]]-r[di[x]]);
     93                     maxx[num1]=max(maxx[num1],a[di[x]]+r[di[x]]);
     94                 }
     95             }
     96         }while(x!=u);
     97     }
     98 }
     99 int lower(long long x){
    100     int ll=1;int rr=tot+1; 
    101     while(ll<=rr){
    102         int mid=(ll+rr)>>1;
    103         if(b[mid]>=x){
    104             tmp=mid;
    105             rr=mid-1;
    106         }
    107         else ll=mid+1;
    108     }
    109     return tmp;
    110 }
    111 int uppr(long long x){
    112     int ll=1;int rr=tot+1; 
    113     while(ll<=rr){
    114         int mid=(ll+rr)>>1;
    115         if(b[mid]>x){
    116             tmp=mid;
    117             rr=mid-1;
    118         }
    119         else ll=mid+1;
    120     }
    121     return tmp;
    122 }
    123 int main(){
    124     scanf("%d",&n);
    125     for(int i=1;i<=n;i++){
    126         scanf("%lld%lld",&a[i],&r[i]);
    127         b[i]=a[i];
    128     }
    129     tot=unique(b+1,b+1+n)-(b+1);
    130     b[tot+1]=4e18;
    131     build(1,n,1);
    132     for(int i=1;i<=n;i++){
    133         int x=lower(a[i]-r[i]);
    134         int y=uppr(a[i]+r[i])-1;
    135         update(x,y,1,id[i]);
    136     }
    137     for(int i=1;i<=num;i++){
    138         if(!dfn[i])Tarjan(i);
    139     } 
    140     for(int i=1;i<=cnt;i++){
    141         if(col[e[i].u]==col[e[i].to])continue;
    142         add1(col[e[i].to],col[e[i].u]);
    143         in[col[e[i].u]]++;
    144     }
    145     for(int i=1;i<=num1;i++){
    146         if(in[i]==0)q.push(i);
    147     }
    148     while(!q.empty()){
    149         int u=q.front();
    150         q.pop();
    151         for(int i=head1[u];i;i=e1[i].nxt){
    152             int v=e1[i].to;
    153             in[v]--;
    154             if(in[v]==0)q.push(v);
    155             minn[v]=min(minn[v],minn[u]);
    156             maxx[v]=max(maxx[v],maxx[u]); 
    157         }
    158     }
    159     for(int i=1;i<=n;i++){
    160         int x=uppr(maxx[col[id[i]]])-1;
    161         int y=lower(minn[col[id[i]]]);
    162         ans+=(long long)((long long)(x-y+1)*(long long)i)%mod;
    163         ans%=mod;
    164     }
    165     printf("%lld",ans);
    166     return 0;
    167 }
    168 
    View Code
  • 相关阅读:
    高能天气——团队博客汇总
    高能天气——团队Scrum冲刺阶段-Day 1-领航
    20172303 2018-2019-1 《程序设计与数据结构》实验三报告
    高能天气——团队作业第二周
    20172303 2018-2019-1《程序设计与数据结构》深度优先遍历
    高能天气——团队作业第一周
    20172322 2018-2019-1《程序设计与数据结构》课程总结
    172322 2018-2019-1 《程序设计与数据结构》哈夫曼编码测试报告
    高能天气——团队Scrum冲刺阶段-Day 3
    172322 2018-2019-1 《程序设计与数据结构》实验三报告
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9407950.html
Copyright © 2020-2023  润新知