CF765F Souvenirs

\[首先考虑离线,固定R,考虑加入R会对前面的答案造成怎样的影响 \\ 然后,规定只统计(i<j且a[i]>a[j]) \\ 找到当前位置能更新的最近的位置,记为now \\ 在now前面的nowp,必须要(a[nowp]-a[i])<|a[nowp]-a[now]|=>(a[nowp])<\dfrac{a[i]+a[now]}{2} \\ 这样每次值域都会减半 \]

#include<bits/stdc++.h>
#define INF 1e9
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
const int MAXN=6e5+5;
struct Segment{
	int lc,rc;
	int date;
}Tree[MAXN*4];
void push_up(int p)
{
	Tree[p].date=max(Tree[ls].date,Tree[rs].date);
}
int root;
int cnt_Tree;
int New()
{
	++cnt_Tree;
	Tree[cnt_Tree].date=0;
	Tree[cnt_Tree].lc=0;
	Tree[cnt_Tree].rc=0;
	return cnt_Tree;
}
void Update(int &p,int l,int r,int x,int k)
{
	if(!p)
	{
		p=New();
	}
	if(l==r)
	{
		Tree[p].date=max(Tree[p].date,k);
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid){
		Update(ls,l,mid,x,k);
	}
	else
	{
		Update(rs,mid+1,r,x,k);
	}
	push_up(p);
}
int Query(int p,int l,int r,int ql,int qr)
{
	if(!p)
	{
		return 0;
	}
	if(l>=ql&&r<=qr)
	{
		return Tree[p].date;
	}
	int mid=(l+r)>>1;
	int res=0;
	if(ql<=mid)
	{
		res=max(res,Query(ls,l,mid,ql,qr));
	}
	if(qr>mid)
	{
		res=max(res,Query(rs,mid+1,r,ql,qr));
	}
	return res;
}
int Bit[MAXN];
int n;
int lowbit(int x){
	return x&(-x);
}
void update(int k,int x)
{
	for(int i=k;i>=1;i-=lowbit(i))
	{
		Bit[i]=min(Bit[i],x);
	}
	return;
}
int	Min(int k)
{
	int res=0x3f3f3f3f;
	for(int i=k;i<=n;i+=lowbit(i))
	{
		res=min(res,Bit[i]);
	}
	return res;
}
int q;
int a[MAXN];
int l,r;
vector<pair<int,int> >ruery[MAXN];
int ans[MAXN];
void Work()
{
	cnt_Tree=0;
	root=0;
	memset(Bit,0x3f,sizeof(Bit));
	for(int i=1;i<=n;i++)
	{
		int now=Query(root,1,INF,a[i]+1,INF);
		while(now)
		{
	//		printf("%d\n",now);
			update(now,a[now]-a[i]);
			//now=Query(root,1,INF,)
			int nexr=(a[now]+a[i]);
			if(nexr%2==0){
				nexr=nexr/2-1;
			}
			else
			{
				nexr=(nexr-1)/2;
			}
			now=Query(root,1,INF,a[i]+1,nexr);
		}
		Update(root,1,INF,a[i],i);
		for(int j=0;j<ruery[i].size();j++)
		{
			ans[ruery[i][j].second]=min(ans[ruery[i][j].second],Min(ruery[i][j].first));
		}
	}
}
int main()
{
	scanf("%d",&n);
	scanf("%d",&q);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	
	for(int i=1;i<=q;i++)
	{
		scanf("%d %d",&l,&r);
		ruery[r].push_back(make_pair(l,i)); 
		ans[i]=0x3f3f3f3f;
	}
	Work();
	for(int i=1;i<=n;i++)
	{
		a[i]=INF-a[i];
	}
	Work();
	for(int i=1;i<=q;i++)
	{
		printf("%d\n",ans[i]);
	}
}
//$$
//首先考虑离线,固定R,考虑加入R会对前面的答案造成怎样的影响
//\\
//然后,规定只统计(i<j且a[i]>a[j])
//\\
//找到当前位置能更新的最近的位置,记为now
//\\
//在now前面的nowp,必须要(a[nowp]-a[i])<|a[nowp]-a[now]|=>(a[nowp])<\dfrac{a[i]+a[now]}{2}
//\\
//这样每次值域都会减半
//$$
posted @ 2022-03-16 21:58  kid_magic  阅读(25)  评论(0编辑  收藏  举报