一个暴力的思想是每个点向能引爆它的点连边,求出强联通分量统计答案。但这样是 O(n2) 的。然后线段树优化建图就好了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
char c=nc(),b=1;
for(;c<'0'||c>'9';c=nc())if(c=='-')b=-1;
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());x*=b;
}
typedef long long ll;
inline void Read(ll& x){
char c=nc(),b=1;
for(;c<'0'||c>'9';c=nc())if(c=='-')b=-1;
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());x*=b;
}
const int N=500010;
const int P=1000000007;
const int M=7000010;
int ls[M],rs[M],num;
int k,n,m;
int h[M],nx[M],t[M],tc,tot;
int dfn[M],low[M],f[M],cnt;
int st[M],top;
int dp[M];
int Rt,q[M],l,r;
int d[M],H[M],Ans;
int L[M],R[M];
int mn[N],mx[N];
ll a[N],b[N];
bool vis[M];
inline void Add(int x,int y){
t[++tot]=y;nx[tot]=h[x];h[x]=tot;
}
inline void Add2(int x,int y){
t[++tot]=y;nx[tot]=H[x];H[x]=tot;d[y]++;
}
void Update(int& x,int l,int r,int y,int z){
if(!x)x=++num;
if(l==r){
Add(x,z);
return;
}
int Mid=l+r>>1;
if(y<=Mid)Update(ls[x],l,Mid,y,z);else Update(rs[x],Mid+1,r,y,z);
}
void Query(int x,int l,int r,int L,int R,int y){
if(!x||l>R||r<L)return;
if(l>=L&&r<=R){
Add(y,x);
return;
}
int Mid=l+r>>1;
Query(ls[x],l,Mid,L,R,y);Query(rs[x],Mid+1,r,L,R,y);
}
inline void Up(int x,int y){
if(y<=n){
L[x]=min(L[x],y);
R[x]=max(R[x],y);
}
}
void Dfs(int x){
dfn[x]=low[x]=++tc;st[++top]=x;
for(int i=h[x];i;i=nx[i]){
int v=t[i];
if(!dfn[v]){
Dfs(v);
low[x]=min(low[x],low[v]);
}else if(!f[v])low[x]=min(low[x],dfn[v]);
}
if(low[x]==dfn[x]){
cnt++;
while(st[top]!=x)Up(cnt,st[top]),f[st[top--]]=cnt;
f[x]=cnt;top--;Up(cnt,x);
}
}
void Solve(int x){
vis[x]=1;
for(int i=H[x];i;i=nx[i]){
int v=t[i];
if(!vis[v])Solve(v);
R[x]=max(R[x],R[v]);L[x]=min(L[x],L[v]);
}
}
int main(){
Read(n);num=n;
for(int i=1;i<=n;i++)Read(a[i]),Read(b[i]),Update(Rt,1,n,i,i);
for(int i=1;i<=n;i++)mn[i]=lower_bound(a+1,a+n+1,a[i]-b[i])-a,mx[i]=(upper_bound(a+1,a+n+1,a[i]+b[i])-a)-1;
for(int i=1;i<=n;i++)Query(Rt,1,n,mn[i],mx[i],i);
for(int i=n+1;i<=num;i++){
if(ls[i])Add(i,ls[i]);
if(rs[i])Add(i,rs[i]);
}
memset(L,127,sizeof(L));
for(int i=1;i<=num;i++)
if(!dfn[i])Dfs(i);
for(int i=1;i<=num;i++)
for(int j=h[i];j;j=nx[j])
if(f[i]!=f[t[j]])Add2(f[i],f[t[j]]);
for(int i=1;i<=cnt;i++)
if(!vis[i])Solve(i);
for(int i=1;i<=n;i++)
Ans=(Ans+1ll*i*(R[f[i]]-L[f[i]]+1))%P;
cout<<Ans<<endl;
return 0;
}