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 }