蒟蒻蜜汁MLE,求助
查看原帖
蒟蒻蜜汁MLE,求助
249736
Seg_Tree楼主2020/7/28 11:01
#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,故也没有去重边

2020/7/28 11:01
加载中...