zoukankan      html  css  js  c++  java
  • bzoj 5017 炸弹

    题目大意:

    直线上有n个炸弹有坐标x和半径r

    当一个炸弹被引爆时 若有炸弹的坐标在该炸弹坐标+-r范围内则另一个炸弹也被引爆

    求先引爆每一个炸弹最终会引爆多少炸弹

    思路:

    可以想到n平方连边然后tarjan缩点跑拓扑

    可以通过线段树来优化建图

    对每个点向它能直接引爆的左右范围连边

    即用线段树中的线段作为点来建图

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MOD 1000000007
    12 #define MAXN 500100
    13 #define MAXM 10010000
    14 #define V1 g1.to[i]
    15 #define V2 g2.to[i]
    16 using namespace std;
    17 inline ll read()
    18 {
    19     ll x=0,f=1;char ch=getchar();
    20     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    21     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    22     return x*f;
    23 }
    24 ll n,m,p[MAXN],rd[MAXN],ans,hsh[MAXN],sl[MAXN<<2],sr[MAXN<<2],l[MAXN<<2],r[MAXN<<2];
    25 int dfn[MAXN<<2],low[MAXN<<2],st[MAXN<<2],bl[MAXN<<2],stp,top,scc;
    26 int q[MAXN<<2],hd=1,tl,ind[MAXN<<2];
    27 struct graph
    28 {
    29     int cnt,fst[MAXN<<2],nxt[MAXM<<1],to[MAXM<<1],ind[MAXN<<2];
    30     graph(){memset(fst,0,sizeof(fst));cnt=0;}
    31     inline void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,ind[v]++;}
    32 }g1,g2;
    33 void build(int k,int l,int r)
    34 {
    35     sl[k]=l,sr[k]=r;
    36     if(l==r) {hsh[l]=k,m=k;return ;}
    37     int mid=l+r>>1;
    38     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    39     g1.add(k,k<<1);g1.add(k,k<<1|1);
    40 }
    41 void mdf(int k,int l,int r,int a,int b,int x)
    42 {
    43     if(l==a&&r==b) {if(l!=r||(l==r&&k!=x)) g1.add(x,k);return ;}
    44     int mid=l+r>>1;
    45     if(b<=mid) mdf(k<<1,l,mid,a,b,x);
    46     else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,x);
    47     else {mdf(k<<1,l,mid,a,mid,x);mdf(k<<1|1,mid+1,r,mid+1,b,x);}
    48 }
    49 void tarjan(int x)
    50 {
    51     dfn[x]=low[x]=++stp,st[++top]=x;
    52     for(int i=g1.fst[x];i;i=g1.nxt[i])
    53         if(!dfn[V1]) {tarjan(V1);low[x]=min(low[x],low[V1]);}
    54         else if(!bl[V1]) low[x]=min(low[x],dfn[V1]);
    55     if(low[x]==dfn[x])
    56     {
    57         l[++scc]=inf;int now=0;
    58         while(now!=x) now=st[top--],bl[now]=scc,l[scc]=min(l[scc],sl[now]),r[scc]=max(r[scc],sr[now]);
    59     }
    60 }
    61 void build()
    62 {
    63     for(int x=1;x<=m;x++)
    64         for(int i=g1.fst[x];i;i=g1.nxt[i])
    65             if(bl[x]!=bl[V1]) g2.add(bl[x],bl[V1]);
    66 }
    67 int main()
    68 {
    69     n=read();build(1,1,n);int a,b;
    70     for(int i=1;i<=n;i++) p[i]=read(),rd[i]=read();
    71     for(int i=1;i<=n;i++)
    72     {
    73         a=lower_bound(p+1,p+n+1,p[i]-rd[i])-p;
    74         b=upper_bound(p+1,p+n+1,p[i]+rd[i])-p-1;
    75         mdf(1,1,n,a,b,hsh[i]);
    76     }
    77     for(int i=1;i<=m;i++) if(!dfn[i]) tarjan(i);
    78     build();for(int i=1;i<=scc;i++) if(!g2.ind[i]) q[++tl]=i;
    79     while(hd<=tl)
    80     {
    81         a=q[hd++];
    82         for(int i=g2.fst[a];i;i=g2.nxt[i])
    83             {g2.ind[V2]--;if(!g2.ind[V2]) q[++tl]=V2;}
    84     }
    85     for(int x=tl;x;x--)
    86         for(int i=g2.fst[q[x]];i;i=g2.nxt[i])
    87             l[q[x]]=min(l[q[x]],l[V2]),r[q[x]]=max(r[q[x]],r[V2]);
    88     for(int i=1;i<=n;i++) (ans+=(i*(r[bl[hsh[i]]]-l[bl[hsh[i]]]+1))%MOD)%=MOD;
    89     printf("%lld
    ",ans);
    90 }
    View Code
  • 相关阅读:
    组合与封装
    继承与派生
    面向对象编程
    subprocess、re、logging模块
    json、pickle、collections、openpyxl模块
    python内置模块
    递归函数与模块
    生成式、面向过程、与函数式
    叠加装饰器与迭代器
    闭包函数与装饰器
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9726722.html
Copyright © 2011-2022 走看看