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\n",ans);
90 }
View Code

 

posted @ 2018-09-29 21:17  jack_yyc  阅读(149)  评论(0编辑  收藏  举报