#include<iostream>
#include<cstdio>
#include<cstring>
#define N 500050
#define MOD 1000000007
using namespace std;
int read(){
char c=getchar();int in=0;
while(c<48 || c>57)c=getchar();
while(c>47 && c<58)in=in*10+c-48,c=getchar();
return in;
}
int x[N],rad[N]; //basic
int scc_l[N<<2],scc_r[N<<2];
struct EDG{
int u,v,nxt;
}edg[N*5][2];
int head[N*5][2],tot_edg[2];
void add_edg(int u,int v,bool d){
edg[++tot_edg[d]][d]={u,v,head[u][d]};
head[u][d]=tot_edg[d];
}
//SEG_TREE
struct TR{
int l,r;
}tr[N*5];
int tid[N<<2];
//tid[u]:u号炸弹在树上的节点编号为tid[u]
void build(int k,int l,int r){ //此处l,r为id
if(l==r){
tr[k]={l,r};
tid[l]=k;
return;
}
int ls=k<<1,rs=(k<<1)+1,mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
tr[k]={l,r};
add_edg(k,ls,0);
add_edg(k,rs,0);
}
void link(int u,int k,int l,int r){ //此处l,r为id,线段树上连边
// if(k==0)getchar();
if(x[u]-rad[u]<=x[l] && x[r]<=x[u]+rad[u]){
if(k==tid[u])return;
add_edg(tid[u],k,0);
return;
}
int ls=k<<1,rs=(k<<1)+1,mid=l+r>>1;
if(x[u]-rad[u]<=x[mid])link(u,ls,l,mid);
if(x[u]+rad[u]>=x[mid+1])link(u,rs,mid+1,r);
}
//tarjan
int scc_num[N<<2],scc_sum;
int dfn[N<<2],low[N<<2],now;
int sta[N<<2],top; //多用栈^v^
bool vis[N<<2];
void tarjan(int u){ //此处u为树上结点编号
int i,v;
sta[++top]=u;
dfn[u]=low[u]=++now;
vis[u]=1;
for(i=head[u][0]; i; i=edg[i][0].nxt){
v=edg[i][0].v;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
} else if(vis[v])
low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u]){
scc_sum++;
do{
scc_num[sta[top]]=scc_sum;
vis[sta[top]]=0;
scc_l[scc_sum]=min(scc_l[scc_sum],tr[sta[top]].l);
scc_r[scc_sum]=max(scc_r[scc_sum],tr[sta[top]].r);
} while(sta[top--]!=u);
}
}
//dfs
void dfs(int u){
int i,v;
vis[u]=1;
for(i=head[u][1]; i; i=edg[i][1].nxt){
v=edg[i][1].v;
if(!vis[v])
dfs(v);
scc_l[u]=min(scc_l[u],scc_l[v]);
scc_r[u]=max(scc_r[u],scc_r[v]);
}
}
int main(){
memset(scc_l,31,sizeof(scc_l));
int n,i,u,v,ans=0;
n=read();
for(i=1; i<=n; i++){
x[i]=read();
rad[i]=read();
}
build(1,1,n);
for(i=1; i<=n; i++)
if(rad[i])
link(i,1,1,n);
tarjan(1);
for(i=1; i<=tot_edg[0]; i++){
u=scc_num[edg[i][0].u];
v=scc_num[edg[i][0].v];
if(u!=v)
add_edg(u,v,1);
}
memset(vis,0,sizeof(vis)); //多用vis ^v^
for(i=1; i<=scc_sum; i++)
if(!vis[i])
dfs(i);
for(i=1; i<=n; i++){
ans=(ans+(scc_r[scc_num[tid[i]]]-scc_l[scc_num[tid[i]]]+1)*i)%MOD;
}
cout<<ans;
}
是第一篇题解的思路,但我没用vector,故也没有去重边