在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足:
Xi?Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆。
现在,请你帮忙计算一下,先把第 i 个炸弹引爆,将引爆多少个炸弹呢?
标签:space none cc++ 引爆 head 半径 isp one tar
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<cstdio> 6 #include<algorithm> 7 #define maxn 500005 8 #define ll long long 9 #define mod 1000000007 10 using namespace std; 11 inline ll read() { 12 char ch=getchar();ll x=0,f=1; 13 for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-1; 14 for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; 15 return x*f; 16 } 17 int n,rt; 18 ll s[maxn*5],a[maxn*5],id[maxn*5],tsz; 19 struct seg {int s[2];ll mn,mx;}t[maxn*5]; 20 struct Edge {int fr,to,nxt;}e[maxn*20]; 21 int head[maxn*5],sz; 22 void addedge(int u,int v) {e[sz].fr=u;e[sz].nxt=head[u];e[sz].to=v;head[u]=sz++;} 23 void build(int l,int r,int &x) { 24 x=++tsz; 25 if(l==r) {id[l]=x;t[x].mn=t[x].mx=l;return;} 26 int mid=l+r>>1; 27 build(l,mid,t[x].s[0]);build(mid+1,r,t[x].s[1]); 28 if(t[x].s[0]) addedge(x,t[x].s[0]); 29 if(t[x].s[1]) addedge(x,t[x].s[1]); 30 t[x].mn=l;t[x].mx=r; 31 return ; 32 } 33 void add(int l,int r,int x,int L,int R,int p) { 34 if(L<=l&&R>=r) {if(id[p]==x) return;addedge(id[p],x);return;} 35 int mid=l+r>>1; 36 if(L<=mid) add(l,mid,t[x].s[0],L,R,p); 37 if(R>mid) add(mid+1,r,t[x].s[1],L,R,p); 38 return; 39 } 40 bool inq[maxn*5]; 41 ll dfn[maxn*5],low[maxn*5],tim,q[maxn*5],top,lm[maxn*5],rm[maxn*5]; 42 int bel[maxn*5],scc; 43 void tarjan(int x) { 44 dfn[x]=low[x]=++tim;q[++top]=x;inq[x]=1; 45 for(int i=head[x];i>=0;i=e[i].nxt) { 46 int to=e[i].to; 47 if(!dfn[to]){ 48 tarjan(to);low[x]=min(low[x],low[to]); 49 }else if(inq[to]) low[x]=min(low[x],dfn[to]); 50 } 51 if(dfn[x]==low[x]) { 52 scc++; 53 lm[scc]=214748364700000000ll; 54 ll now; 55 do { 56 now=q[top--];inq[now]=0;bel[now]=scc; 57 lm[scc]=min(lm[scc],t[now].mn);rm[scc]=max(rm[scc],t[now].mx); 58 }while(now!=x); 59 } 60 } 61 ll rd[maxn*5]; 62 int main() { 63 //freopen("bomb9.in","r",stdin); 64 memset(head,-1,sizeof(head)); 65 n=read(); 66 for(int i=1;i<=n;i++) {s[i]=read();a[i]=read();} 67 build(1,n,rt); 68 for(int i=1;i<=n;i++) { 69 int now=lower_bound(s+1,s+n+1,s[i])-s,L=lower_bound(s+1,s+n+1,s[i]-a[i])-s,R=upper_bound(s+1,s+n+1,s[i]+a[i])-s-1; 70 if(L==R) continue;add(1,n,1,L,R,i); 71 } 72 for(int i=1;i<=tsz;i++) if(!dfn[i]) {tarjan(i);} 73 int tmp=sz;sz=0;memset(head,-1,sizeof(head)); 74 for(int i=0;i<tmp;i++) { 75 int u=bel[e[i].fr],v=bel[e[i].to]; 76 if(u==v) continue; 77 rd[v]++;addedge(u,v); 78 } 79 int hd=0,tl=0; 80 for(int i=1;i<=scc;i++) if(!rd[i]) q[tl++]=i; 81 while(hd!=tl) { 82 int now=q[hd++]; 83 for(int i=head[now];i>=0;i=e[i].nxt) { 84 int to=e[i].to;rd[to]--; 85 if(!rd[to]) q[tl++]=to; 86 } 87 } 88 for(int i=scc;i>=1;i--) { 89 int now=q[i]; 90 for(int j=head[now];j>=0;j=e[j].nxt) { 91 int to=e[j].to; 92 lm[now]=min(lm[now],lm[to]);rm[now]=max(rm[now],rm[to]); 93 } 94 } 95 ll ans=0; 96 for(int i=1;i<=n;i++) { 97 ans+=(ll)i*(rm[bel[id[i]]]-lm[bel[id[i]]]+1);ans%=mod; 98 } 99 printf("%lld\n",ans); 100 } 101
[bzoj5017][Snoi2017]炸弹 tarjan缩点+线段树优化建图+拓扑
标签:space none cc++ 引爆 head 半径 isp one tar
原文地址:https://www.cnblogs.com/wls001/p/9718028.html