萌新86分求助,WA1,2,Tarjan+缩点+线段树
查看原帖
萌新86分求助,WA1,2,Tarjan+缩点+线段树
109625
HKHbest楼主2020/10/2 12:28

思路就是题解中常见的线段树上跑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 大法好

2020/10/2 12:28
加载中...