CF765F Souvenirs

Souvenirs

给出 (n) 以及一个长为 (n) 的序列 (a)

给出 (m),接下来 (m) 组询问。每组询问给出一个 (l,r),你需要求出,对于 (i,j in [l,r]),且满足 (i eq j)(|a_i-a_j|) 的最小值。

(1 leq n leq 10^5)(1 leq m leq 3 imes 10^5)(0 leq a_i leq 10^9)

题解

https://www.cnblogs.com/CQzhangyu/p/8468825.html

[a_{j'}-a_i< a_j-a_{j'}\ 2(a_{j'}-a_i)< a_j-a_i\ ]

所以每次差会减半。

怎么找 (a_j) 呢?按照从大到小的顺序插入线段树然后在线段树上二分即可。

然后每个贡献可以写成点对的形式,就转化成了一个二维偏序。

时间复杂度 (O(nlog nlog v))

CO int N=1e5+10,inf=2e9;
int a[N],o[N];

namespace seg{
	int s[4*N];

	#define lc (x<<1)
	#define rc (x<<1|1)
	#define mid ((l+r)>>1)
	void build(int x,int l,int r){
		s[x]=inf;
		if(l==r) return;
		build(lc,l,mid),build(rc,mid+1,r);
	}
	void insert(int x,int l,int r,int p,int v){
		s[x]=min(s[x],v);
		if(l==r) return;
		if(p<=mid) insert(lc,l,mid,p,v);
		else insert(rc,mid+1,r,p,v);
	}
	int query(int x,int l,int r,int p,int v){
		if(p<l) return 0;
		if(r<=p){
			if(s[x]>v) return 0;
			if(l==r) return l;
			if(s[rc]<=v) return query(rc,mid+1,r,p,v);
			else return query(lc,l,mid,p,v);
		}
		if(p<=mid) return query(lc,l,mid,p,v);
		int ans=query(rc,mid+1,r,p,v);
		if(ans) return ans;
		return query(lc,l,mid,p,v);
	}
	#undef lc
	#undef rc
	#undef mid
}

namespace bit{
	int n,s[N];
	
	void init(int n){
		bit::n=n,fill(s+1,s+n+1,inf);
	}
	#define lowbit(x) (x&-x)
	void insert(int p,int v){
		for(int i=p;i;i-=lowbit(i)) s[i]=min(s[i],v);
	}
	int query(int p){
		int ans=inf;
		for(int i=p;i<=n;i+=lowbit(i)) ans=min(ans,s[i]);
		return ans;
	}
	#undef lowbit
}

struct point {int x,y,v;} p[N*30],q[3*N];
int ans[3*N];

void solve(int n,int m){
	for(int i=1;i<=n;++i) o[i]=i;
	sort(o+1,o+n+1,[](int i,int j)->bool{
		return a[i]!=a[j]?a[i]>a[j]:i<j; // edit 1: i<j
	});
	seg::build(1,1,n);
	int tot=0;
	for(int i=1;i<=n;++i){
		seg::insert(1,1,n,o[i],a[o[i]]);
		int j=seg::query(1,1,n,o[i]-1,inf-1);
		if(!j) continue;
		do p[++tot]={j,o[i],a[j]-a[o[i]]};
		while((j=seg::query(1,1,n,j-1,(a[o[i]]+a[j]+1)/2-1)));
	}
	sort(p+1,p+tot+1,[](CO point&a,CO point&b)->bool{
		return a.y<b.y;
	});
	sort(q+1,q+m+1,[](CO point&a,CO point&b)->bool{
		return a.y<b.y;
	});
	bit::init(n);
	for(int i=1,j=1;i<=tot or j<=m;){
		if(j>m or (i<=tot and p[i].y<=q[j].y)){
			bit::insert(p[i].x,p[i].v);
			++i;
		}
		else{
			ans[q[j].v]=min(ans[q[j].v],bit::query(q[j].x));
			++j;
		}
	}
}
int main(){
	int n=read<int>();
	for(int i=1;i<=n;++i) read(a[i]);
	int m=read<int>();
	for(int i=1;i<=m;++i) read(q[i].x),read(q[i].y),q[i].v=i;
	fill(ans+1,ans+m+1,inf);
	solve(n,m);
	for(int i=1;i<=n;++i) a[i]=1e9-a[i];
	solve(n,m);
	for(int i=1;i<=m;++i) printf("%d
",ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/autoint/p/12520137.html