P10466 邻值查找 题解

题目传送门

前置知识

二叉搜索树 & 平衡树

解法

笔者写这篇题解的时候题面应该是出锅了,建议去看 Acwing 的题面。

第一问同 luogu P2234 [HNOI2002] 营业额统计 ,平衡树维护前驱、后继(非严格意义上的)求出差值后取 \(\min\) 即可;第二问用 map 实现一个映射即可维护位置。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
const ll INF=0x3f3f3f3f3f3f3f3f;
ll rt_sum=0;
map<ll,ll>f;
struct Treap
{
    ll son[2],val,rnd,cnt,siz;
}tree[100010];
#define lson(rt) (tree[rt].son[0])
#define rson(rt) (tree[rt].son[1])
#define dson(rt,d) (tree[rt].son[d])
#define ason(rt,d) (tree[rt].son[d^1])
void pushup(ll rt)
{
    tree[rt].siz=tree[lson(rt)].siz+tree[rson(rt)].siz+tree[rt].cnt;
}
ll build(ll val)
{
    rt_sum++;
    lson(rt_sum)=rson(rt_sum)=0;
    tree[rt_sum].val=val;
    tree[rt_sum].rnd=rand();
    tree[rt_sum].cnt=tree[rt_sum].siz=1;
    return rt_sum;
}
void rotate(ll &rt,ll d)
{
    ll lsrt=ason(rt,d);
    ason(rt,d)=dson(lsrt,d);
    dson(lsrt,d)=rt;
    pushup(rt);
    rt=lsrt;
    pushup(rt);
}
void insert(ll &rt,ll val)
{
    if(rt==0)
    {
        rt=build(val);
    }
    else
    {
        if(tree[rt].val==val)
        {
            tree[rt].cnt++;
            tree[rt].siz++;
        }
        else
        {
            ll d=(val>tree[rt].val);
            insert(dson(rt,d),val);
            if(tree[rt].rnd<tree[dson(rt,d)].rnd)
            {
                rotate(rt,d^1);
            }
            pushup(rt);
        }
    }
}
ll query_pre(ll rt,ll val)
{
    if(rt==0)
    {
        return -INF;
    }
    if(tree[rt].val<val)
    {
        return max(tree[rt].val,query_pre(rson(rt),val));
    }
    else
    {
        return query_pre(lson(rt),val);
    }
}
ll query_lower(ll rt,ll val)
{
    if(rt==0)
    {
        return INF;
    }
    if(tree[rt].val>=val)
    {
        return min(tree[rt].val,query_lower(lson(rt),val));
    }
    else
    {
        return query_lower(rson(rt),val);
    }
}
int main()
{
    ll n,x,rt=0,sum1,sum2,i;
    srand(time(0));
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>x;
		if(i>=2)
		{
			sum1=query_pre(rt,x);
			sum2=query_lower(rt,x);
			if(x-sum1<sum2-x)
			{
				cout<<x-sum1<<" "<<f[sum1]<<endl;
			}
			if(x-sum1==sum2-x)
			{
				cout<<x-sum1<<" "<<f[min(sum1,sum2)]<<endl;
			}
			if(x-sum1>sum2-x)
			{
				cout<<sum2-x<<" "<<f[sum2]<<endl;
			}
		}
        insert(rt,x);
		if(f.find(x)==f.end())
		{
			f[x]=i;
		}
    }
    return 0;
}
posted @ 2024-06-08 12:57  hzoi_Shadow  阅读(24)  评论(0编辑  收藏  举报
扩大
缩小