WA 44pts求调(已知不是数组和LL的问题)
查看原帖
WA 44pts求调(已知不是数组和LL的问题)
881015
Resstifnurvˆwˆ.tar.gz楼主2024/2/28 12:00
  • 数组已经开到 6×1066×10^6,应该可以排除数组开小了
  • 会爆int的地方已经开了long long,且试过 #define int long long,没有变化
  • 跟着题解写的,写完后对照了一遍,似乎没有什么细节上的区别
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<utility>
using namespace std;
typedef long long ll;

inline ll read(){
	ll ret=0;
	char ch=' ',c=getchar();
	while(!('0'<=c&&c<='9')) ch=c,c=getchar();
	while('0'<=c&&c<='9') ret=(ret<<1)+(ret<<3)+(c^48),c=getchar();
	return ch=='-'?-ret:ret;
}

int n,tot=0;
const int N=6e6+10,M=1e7+10;
int np[N];
bool is_real[N];
ll pos[N],ran[N];

struct graph{
	int to[M],nt[M],idx,h[N];
	inline void add(int x,int y){
		to[idx]=y;
		nt[idx]=h[x];
		h[x]=idx++;
	}
	graph(){
		idx=0;
		memset(h,-1,sizeof(h));
	}
} ori,ano;

struct NODE{
	int l,r;
} tr[N];

void build(int u,int l,int r){
	tr[u]=(NODE){l,r};
	tot=max(tot,u);
	if(l==r){
		np[l]=u;
		is_real[u]=true;
		return ;
	}
	int mid=(l+r)>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	ori.add(u,u<<1);
	ori.add(u,u<<1|1);
}

void modify(int u,int l,int r,int fa){
	if(l<=tr[u].l&&tr[u].r<=r){
		ori.add(fa,u);
		return ;
	}
	int mid=(tr[u].l+tr[u].r)>>1;
	if(l<=mid) modify(u<<1,l,r,fa);
	if(r>mid) modify(u<<1|1,l,r,fa);
}

int timestamp=0;
int dfn[N];
int low[N];

int stk[N];
int hh=0,tt=-1;
bool instk[N];
int scc_cnt=0;
int id[N],sz[N];
int zuo[N],you[N];

void tarjan(int u){
	timestamp++;
	dfn[u]=timestamp;
	low[u]=timestamp;
	stk[++tt]=u;
	instk[u]=true;
	for(int i=ori.h[u];i!=-1;i=ori.nt[i]){
		int j=ori.to[i];
		if(!dfn[j]){
			tarjan(j);
			low[u]=min(low[u],low[j]);
		}
		else if(instk[j]){
			low[u]=min(low[u],dfn[j]);
		}
	}
	if(dfn[u]==low[u]){
		scc_cnt++;
		zuo[scc_cnt]=0x3f3f3f3f;
		int t;
//		printf("=====scc #%d:\n",scc_cnt);
		do{
			t=stk[tt--];
			instk[t]=false;
			id[t]=scc_cnt;
			if(is_real[t]) sz[scc_cnt]++;
			zuo[scc_cnt]=min(zuo[scc_cnt],tr[t].l);
			you[scc_cnt]=max(you[scc_cnt],tr[t].r);
//			printf("%d ",t);
		}while(t!=u);
//		printf("\n===zuo:%d you:%d\n",zuo[scc_cnt],you[scc_cnt]);
	}
}

bool v[N];
void dfs(int u){
//	printf("===u:%d\n",u);
	v[u]=true;
	for(int i=ano.h[u];i!=-1;i=ano.nt[i]){
		int j=ano.to[i];
//		printf("update %d;\n",j);
		if(!v[j]) dfs(j);
		zuo[u]=min(zuo[u],zuo[j]);
		you[u]=max(you[u],you[j]);
	}
}

vector<ll> vct;
int upb(ll x){
	int l=1,r=n,mid;
	while(l<r){
		mid=(l+r)>>1;
		if(vct[mid]>=x) r=mid;
		else l=mid+1;
	}
	return l;
}
int lob(ll x){
	int l=1,r=n,mid;
	while(l<r){
		mid=(l+r+1)>>1;
		if(vct[mid]<=x) l=mid;
		else r=mid-1;
	}
	return l;
}

int main(){
	vct.push_back(0xc3c3c3c3c3c3c3c3);
	n=read();
	for(int i=1;i<=n;i++){
		pos[i]=read(),ran[i]=read();
		vct.push_back(pos[i]);
	}
//	vct.push_back(0x3f3f3f3f3f3f3f3f);
	build(1,1,n);
	for(int i=1;i<=n;i++){
		int l=upb(pos[i]-ran[i]);
		int r=lob(pos[i]+ran[i]);
//		printf("[%d,%d]\n",l,r);
		modify(1,l,r,np[i]);
	}
	tarjan(1);
	for(int u=1;u<=tot;u++){
		for(int i=ori.h[u];i!=-1;i=ori.nt[i]){
			int j=ori.to[i];
//			printf("i=%d j=%d\n",u,j);
			if(id[u]!=id[j]){
				ano.add(id[u],id[j]);
//				printf("add(%d->%d)\n",id[u],id[j]);
			}
		}
	}
	for(int i=1;i<=scc_cnt;i++) dfs(i);
	ll ans=0;
	for(ll i=1;i<=n;i++){
//		printf("#%d: %d->%d\n",i,zuo[id[np[i]]],you[id[np[i]]]);
		ans+=i*(you[id[np[i]]]-zuo[id[np[i]]]+1);
	}
	printf("%lld",ans);
	return 0;
}
2024/2/28 12:00
加载中...