Solution
- This question can direct a bomb to a bomb it can detonate with a directed edge
- Then search for the number of bombs that a bomb can reach along the directed edge in the built graph
- It seems that it can be optimized with the contraction point of the strong Unicom component?
Since the bomb that each bomb can detonate must be a continuous section, you can record which section of bomb represents each retracted point when retracting
After shrinking the point, dfs again finds out which segment can be detonated
But the person who made the question is too malicious and needs to connect n 2 sides. . .
Since the connected edges are always a range, we consider whether we can use line tree optimization
Build a line segment tree with n leaf nodes (the father connects to the son with an order of magnitude n), and use each bomb as the leaf node corresponding to the number
Then connect the edges to the corresponding line segment when connecting the edges, the total number of connected edges is within the order of nlogn
Code
#include <cstdio> #include <cstdlib> #include <vector> #include <cstring> #include <algorithm> #define ll long long #define mid ((l+r)>>1) #define lc (g<<1) #define rc ((g<<1)|1) using namespace std; const int N=5e5+10,M=2e6+10,P=1e9+7; vector <int> link[M],son[M],re[M]; int n,id[N],scc,d[M],le[M],ri[M],m; int top,dfn[M],low[M],tot,st[M],in[M],ans; ll x[N],r[N]; struct node { int l,r; inline node(int l=0,int r=0):l(l),r(r){}; }f[M]; void build(int g,int l,int r) { f[g]=node(l,r); m=max(m,g); if(l==r) { id[l]=g; return; } link[g].push_back(lc); link[g].push_back(rc); build(lc,l,mid); build(rc,mid+1,r); } void add(int g,int l,int r,int ul,int ur,int v) { if(ul<=l && r<=ur) { link[v].push_back(g); return; } if(ur<=mid) add(lc,l,mid,ul,ur,v); else if(ul>mid) add(rc,mid+1,r,ul,ur,v); else add(lc,l,mid,ul,mid,v),add(rc,mid+1,r,mid+1,ur,v); } void tarjan(int u) { dfn[u]=low[u]=++tot; st[++top]=u,in[u]=1; int size=link[u].size(); for(int i=0;i<size;i++) { int v=link[u][i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(in[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { scc++; int z=0; do { z=st[top--]; d[z]=scc,in[z]=0; le[scc]=min(le[scc],f[z].l); ri[scc]=max(ri[scc],f[z].r); }while(z!=u); } } void dfs(int u) { in[u]=1; int size=re[u].size(); for(int i=0;i<size;i++) { int v=re[u][i]; if(!in[v]) dfs(v); le[u]=min(le[u],le[v]); ri[u]=max(ri[u],ri[v]); } } int query(int x) { int u=d[id[x]]; return ri[u]-le[u]+1; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld%lld",&x[i],&r[i]); build(1,1,n); for(int i=1;i<=n;i++) { int L=lower_bound(x+1,x+1+n,x[i]-r[i])-x; int R=upper_bound(x+1,x+1+n,x[i]+r[i])-x-1; add(1,1,n,L,R,id[i]); } memset(le,0x3f,sizeof(le)); tarjan(1); for(int u=1;u<=m;u++) { int size=link[u].size(); for(int i=0,v;i<size;i++) if(d[v=link[u][i]]!=d[u]) re[d[u]].push_back(d[v]); } dfs(d[1]); for(int i=1;i<=n;i++) ans=(ans+(ll)query(i)*i%P)%P; printf("%d",ans); return 0; }