线段树优化建边好题
但是数据太水了
发现每个炸弹干涉的区间是连续的考虑优化建边
然后明显Tarjan缩点
这里需要发现一个性质
因为对于一张top图寻找从一个点开始到别的点所有siz没有On做法
唯一的比较优的做法是bitset优化的传递闭包
但是这道题不一样
观察发现联通块是连续的所以记录一下向左最远和向右最远
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#include<stack>
typedef int INT;
const int INF=1e9+7;
const int mod=1e9+7;
#define int long long
#define lc (p<<1)
#define rc (p<<1|1)
const int N=8e5+100;
namespace fastIO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//fread->read
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1){IOerror=1;return -1;}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void read(ll &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
inline void read(double &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (ch=='.'){
double tmp=1; ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
}
if (sign)x=-x;
}
inline void read(char *s){
char ch=nc();
for (;blank(ch);ch=nc());
if (IOerror)return;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-1;return;}
}
//getchar->read
inline void read1(int &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (bo)x=-x;
}
inline void read1(double &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (ch=='.'){
double tmp=1;
for (ch=getchar();ch>='0'&&ch<='9';tmp/=10.0,x+=tmp*(ch-'0'),ch=getchar());
}
if (bo)x=-x;
}
inline void read1(char *s){
char ch=getchar();
for (;blank(ch);ch=getchar());
for (;!blank(ch);ch=getchar())*s++=ch;
*s=0;
}
inline void read1(char &c){for (c=getchar();blank(c);c=getchar());}
//scanf->read
inline void read2(int &x){scanf("%d",&x);}
inline void read2(double &x){scanf("%lf",&x);}
inline void read2(char *s){scanf("%s",s);}
inline void read2(char &c){scanf(" %c",&c);}
inline void readln2(char *s){gets(s);}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-12)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
//puts->write
char Out[OUT_SIZE],*o=Out;
inline void print1(int x){
static char buf[15];
char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
while(x)*p1++=x%10+'0',x/=10;
while(p1--!=buf)*o++=*p1;
}
inline void println1(int x){print1(x);*o++='\n';}
inline void print1(char c){*o++=c;}
inline void println1(char c){*o++=c;*o++='\n';}
inline void print1(char *s){while (*s)*o++=*s++;}
inline void println1(char *s){print1(s);*o++='\n';}
inline void println1(){*o++='\n';}
inline void flush1(){if (o!=Out){if (*(o-1)=='\n')*--o=0;puts(Out);}}
struct puts_write{
~puts_write(){flush1();}
}_puts;
inline void print2(int x){printf("%d",x);}
inline void println2(int x){printf("%d\n",x);}
inline void print2(char x){printf("%c",x);}
inline void println2(char x){printf("%c\n",x);}
inline void println2(){printf("\n");}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;
struct Node{
int x,r;
}A[N];
struct Front_star{
int u,v,nxt;
}e[N<<3];
int cnt=0;
int first[N<<2];
void add(int u,int v){
++cnt;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].nxt=first[u];
first[u]=cnt;
}
int rd[N<<2];
int ecnt=0;
int head[N<<2];
void Insert(int u,int v){
++ecnt;
++rd[v];
e[ecnt].u=u;
e[ecnt].v=v;
e[ecnt].nxt=head[u];
head[u]=ecnt;
}
int lson[N<<2];
int rson[N<<2];
int Id[N];
int tot=0;
int n;
void Build(int p,int l,int r){
lson[p]=l;
rson[p]=r;
tot=max(tot,p);
if(l==r){
Id[l]=p;
return;
}
int mid=(l+r)>>1;
add(p,lc);
add(p,rc);
Build(lc,l,mid);
Build(rc,mid+1,r);
}
void Update(int p,int l,int r,int rt){
if(l<=lson[p]&&rson[p]<=r){
add(rt,p);
return;
}
int mid=(lson[p]+rson[p])>>1;
if(l<=mid)Update(lc,l,r,rt);
if(mid< r)Update(rc,l,r,rt);
}
//
//
int pos[N];
stack<int> S;
int Q[N<<2];
int he=0;
int ta=0;
int low[N<<2];
int dfn[N<<2];
int vis[N<<2];
int Belong[N<<2];
int scc=0;
int tcnt=0;
int L[N<<2],R[N<<2];
void Tarjan(int u){
low[u]=dfn[u]=++tcnt;
S.push(u);
vis[u]=1;
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else{
if(vis[v])low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
int x;
scc++;
L[scc]=INF;
do{
x=S.top();
S.pop();
vis[x]=0;
L[scc]=min(L[scc],lson[x]);
R[scc]=max(R[scc],rson[x]);
Belong[x]=scc;
}while(x!=u);
}
}
void Rebuild(){
for(int u=1;u<=tot;++u){
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(Belong[u]!=Belong[v]){
Insert(Belong[u],Belong[v]);
}
}
}
}
void TopSort(){
for(int i=1;i<=scc;++i){
if(!rd[i])Q[++ta]=i;
}
while(he<ta){
int x=Q[++he];
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].v;
rd[v]--;
if(!rd[v])Q[++ta]=v;
}
}
for(int i=scc;i>=1;--i){
int x=Q[i];
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].v;
L[x]=min(L[v],L[x]);
R[x]=max(R[v],R[x]);
}
}
}
INT main(){
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
int size=40<<20;//40M
__asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));
read(n);
for(int i=1;i<=n;++i){
read(A[i].x);
read(A[i].r);
pos[i]=A[i].x;
}
Build(1,1,n);
for(int i=1;i<=n;++i){
int lpos=lower_bound(pos+1,pos+1+n,A[i].x-A[i].r)-pos;
int rpos=upper_bound(pos+1,pos+1+n,A[i].x+A[i].r)-pos-1;
if(lpos==rpos)continue;
Update(1,lpos,rpos,Id[i]);
}
for(int i=1;i<=tot;++i){
if(!dfn[i])Tarjan(i);
}
Rebuild();
TopSort();
int ans=0;
for(int i=1;i<=n;++i){
ans=(ans+i*(R[Belong[Id[i]]]-L[Belong[Id[i]]]+1)%mod)%mod;
}
cout<<ans;
exit(0);
}