妹子刚学线段树优化建图+缩点求调
查看原帖
妹子刚学线段树优化建图+缩点求调
556545
_anll_楼主2024/7/31 14:51

rt,不写动态开点 52pts TLE+MLE,改成动态开点后 TLE+RE+WA 44pts,实在看不出来求调QAQ!

#include<map>
#include<queue>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#define mid (l+r)/2
#define lc tr[p].son[0]
#define rc tr[p].son[1]
#define int long long
using namespace std;
const int N=1e6+5,M=5e5+5,mod=1e9+7;
struct Tr{
	int son[2];
}tr[N*6];
struct Edge{
	int l,nxt;
}edges[N<<1];
int n,www,num[M],ru[M][2];
int tid,rt[2],tt=1,head[N];
int tot,dfn[N],low[N];
int top,stk[N],instk[N];
int cnt,scc[N],scs[N][2];
int ans,du[N],anu[N][2],ann[N];
queue<int> qo;
vector<int> vo;
vector<pair<int,int> > ed;
map<pair<int,int>,int> mp;
unordered_map<int,int> mo;
void add_edge(int f,int l){
	edges[++tt]={l,head[f]};
	head[f]=tt;
	ed.push_back({f,l});
}
void add(int f,int l){
	edges[++tt]={l,head[f]};
	head[f]=tt;
}
//0从区间到单点,1从单点到区间 
void pushup(int p){
	add_edge(p,lc);add_edge(p,rc);
}
void build(int l,int r,int p){
	if(l==r){
		add_edge(p,l);
		return;
	}
	lc=++tid;build(l,mid,lc);
	rc=++tid;build(mid+1,r,rc);
	pushup(p);
}
void update(int L,int R,int l,int r,int p,int a){
	if(L<=l&&r<=R){
		add_edge(a,p);
		return;
	}
	if(L<=mid) update(L,R,l,mid,lc,a);
	if(mid<R) update(L,R,mid+1,r,rc,a);
}
void tarjan(int x){
	dfn[x]=low[x]=++tot;
	stk[++top]=x,instk[x]=1;
	for(int i=head[x];i;i=edges[i].nxt){
		int l=edges[i].l;
		if(!low[l]){
			tarjan(l);
			low[x]=min(low[x],low[l]); 
		}
		else if(instk[l]) low[x]=min(low[x],dfn[l]);
	}
	if(low[x]==dfn[x]){
		int y;cnt++;scs[cnt][0]=2147483647;
		do{
			y=stk[top--];instk[y]=0;
			scc[y]=cnt;
			if(1<=y&&y<=www){
				scs[cnt][0]=min(scs[cnt][0],y);
				scs[cnt][1]=max(scs[cnt][1],y);
			}
			
		}while(x!=y);
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n;int x,y;
	for(int i=1;i<=n;i++){
		cin>>x>>y;num[i]=x,ru[i][0]=y;
		vo.push_back(x);vo.push_back(x+y);vo.push_back(x-y);
	}
	sort(vo.begin(),vo.end());
	mo[vo[0]]=1;int tot=1;
	for(int i=1;i<vo.size();i++){
		if(vo[i]!=vo[i-1]) mo[vo[i]]=++tot;
	}
	for(int i=1;i<=n;i++){
		x=num[i],y=ru[i][0];
		num[i]=mo[x];ann[mo[x]]++;ru[i][0]=mo[x-y],ru[i][1]=mo[x+y];
	}
	for(int i=1;i<=tot;i++) ann[i]+=ann[i-1];
	mo.clear();vo.clear();
	tid=tot;www=tot;
	rt[1]=++tid;build(1,tot,rt[1]);
	for(int i=1;i<=n;i++){
		update(ru[i][0],ru[i][1],1,tot,rt[1],num[i]);
	}
	for(int i=1;i<=n;i++) if(!dfn[num[i]]) tarjan(num[i]);
	tt=1;memset(head,0,sizeof(head));
	for(int i=0;i<ed.size();i++){
		int f=ed[i].first,l=ed[i].second;
		if(scc[f]!=scc[l]&&scc[f]&&scc[l]&&!mp[{f,l}]){
			add(scc[l],scc[f]);
			mp[{f,l}]=1;du[scc[f]]++;
		}
	}
	ed.clear(),mp.clear();
	for(int i=1;i<=cnt;i++){
		anu[i][0]=2147483647;
		if(!du[i]) qo.push(i);
	}
	while(!qo.empty()){
		x=qo.front();qo.pop();
		anu[x][0]=min(anu[x][0],scs[x][0]);
		anu[x][1]=max(anu[x][1],scs[x][1]);
		for(int i=head[x];i;i=edges[i].nxt){
			int l=edges[i].l;du[l]--;
			anu[l][0]=min(anu[l][0],anu[x][0]);
			anu[l][1]=max(anu[l][1],anu[x][1]);
			if(!du[l]) qo.push(l);
		}
	}
	for(int i=1;i<=n;i++) ans=(ans+(i*(
	ann[anu[scc[num[i]]][1]]-ann[anu[scc[num[i]]][0]-1]))%mod)%mod;
	cout<<ans;
	return 0;
}
/*
4
1 1
5 1
6 5
15 15
*/
2024/7/31 14:51
加载中...