思路就是题解中常见的线段树上跑Tarjan强连通分量,缩点再在DAG上跑答案。但WA了前2个点。
(我也在别的OJ上A了(iДi))
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2000005,YCX=1000000007;
int n,m,cnt,le[N],ri[N],X[N],R[N],head[N],id[N],tn,mr;
int top,dfn[N*4],low[N*4],st,zhan[N*4],scc,belong[N*4],rel[N*4],rer[N*4];
long long ans=0;
bool inq[N*4];
int _max(int a,int b)
{
return a>b?a:b;
}
int _min(int a,int b)
{
return a<b?a:b;
}
inline int read()
{
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*w;
}
struct xianduantree
{
int l,r;
}tree[N*4];
struct bian
{
int nxt,to;
}b[N*4];
void add(int from,int to)
{
b[++cnt].nxt=head[from];
b[cnt].to=to;
head[from]=cnt;
}
void build(int cur,int l,int r)
{
tree[cur].l=l;
tree[cur].r=r;
if(l==r)
{
id[l]=cur;
tn=_max(cur,tn);
return;
}
int mid=(l+r)/2;
build(cur*2,l,mid);
build(cur*2+1,mid+1,r);
add(cur,cur*2);
add(cur,cur*2+1);
}
void link(int cur,int jl,int jr,int from)
{
if(tree[cur].l>jr||tree[cur].r<jl)
return;
if(jl<=tree[cur].l&&tree[cur].r<=jr)
{
if(from!=cur)add(from,cur);
return;
}
link(cur*2,jl,jr,from);
link(cur*2+1,jl,jr,from);
}
void Tarjan(int cur)
{
zhan[++top]=cur;
dfn[cur]=low[cur]=++st;
inq[cur]=true;
int i=head[cur],v;
while(i!=0)
{
v=b[i].to;
if(dfn[v]==0)
{
Tarjan(v);
low[cur]=_min(low[cur],low[v]);
}
else if(inq[v]==true)
{
low[cur]=_min(low[cur],dfn[v]);
}
i=b[i].nxt;
}
if(dfn[cur]==low[cur])
{
++scc;
rel[scc]=0x7fffffff;
int ding;
do
{
ding=zhan[top];
belong[ding]=scc;
rel[scc]=_min(rel[scc],tree[ding].l);
rer[scc]=_max(rer[scc],tree[ding].r);
inq[ding]=false;
zhan[top--]=0;
}while(ding!=cur);
}
}
void cha(int i)
{
int l=1,r=n,mid;
while(l<r)
{
mid=(l+r)/2;
if(X[mid]>=X[i]-R[i])
{
r=mid;
}
else
{
l=mid+1;
}
}
le[i]=l;
l=1,r=n;
while(l<r)
{
mid=(l+r+1)/2;
if(X[mid]>X[i]+R[i])
{
r=mid-1;
}
else
{
l=mid;
}
}
ri[i]=l;
}
struct rebian
{
int nxt,to;
}reb[N*4];
int rehead[N*4];
void readd(int from,int to)
{
reb[++cnt].nxt=rehead[from];
reb[cnt].to=to;
rehead[from]=cnt;
}
void rebuild()
{
for(int i=1;i<=tn;i++)
{
for(int j=head[i],v;j!=0;j=b[j].nxt)
{
v=b[j].to;
if(belong[i]!=belong[v])
{
// printf("%d %d\n",belong[i],belong[v]);
readd(belong[i],belong[v]);
}
}
}
}
queue<int> q;
void dfs()
{
for(int i=1;i<=n;i++)
{
if(inq[belong[id[i]]]==false)
{
q.push(belong[id[i]]);
inq[belong[id[i]]]=true;
}
}
int cur,i,v;
while(q.empty()==false)
{
cur=q.front();
q.pop();
i=rehead[cur];
while(i!=0)
{
v=reb[i].to;
rel[cur]=_min(rel[v],rel[cur]);
rer[cur]=_max(rer[v],rer[cur]);
if(inq[v]==false)
q.push(v);
i=reb[i].nxt;
}
}
}
signed main()
{
n=read();
for(int i=1;i<=n;i++)
{
X[i]=read();
R[i]=read();
}
build(1,1,n);
for(int i=1;i<=n;i++)
{
cha(i);
link(1,le[i],ri[i],id[i]);
}
Tarjan(1);
cnt=0;
rebuild();
dfs();
for(int i=1;i<=n;i++)
{
ans+=(i*(rer[belong[id[i]]]-rel[belong[id[i]]]+1))%YCX;
ans%=YCX;
}
printf("%lld\n",ans);
return 0;
}
define int long long 大法好