P3850 [TJOI2007] 书架

P3850 [TJOI2007] 书架

[TJOI2007] 书架

题目描述

Knuth 先生家里有个精致的书架,书架上有 \(N\) 本书,如今他想学到更多的知识,于是又买来了 \(M\) 本不同的新书。现在他要把新买的书依次插入到书架中,他已经把每本书要插入的位置标记好了,并且相应的将它们放好。由于 Knuth 年龄已大,过几天他已经记不清某些位置上放的到底是什么书了,请问你能帮助他吗?

对于 \(100\%\) 的数据,\(1 \leqslant N \leqslant 200\), \(1 \leqslant M \leqslant 10^5\), \(1 \leqslant Q \leqslant 10^4\). 保证输入合法

Solution:

最近线段树写吐了捏,来写平衡树捏,平衡树好写捏。

其实我没太搞懂这是怎么评到紫的,我们只需要按照题面维护一颗平衡树,然后对于每个插入操作 (x,k),将 FHQ-Treap 的前 k 个节点splite出来,然后再按照 (L,x,R) 的顺序 merge 回去。
查询也是直接 splite 然后输出,再 merge

感觉没什么难的,几乎没有任何思维难度。

感觉这个甚至比平衡树模板简单

点击此处与妙妙思维平衡题一决高下

Code:

#include<bits/stdc++.h>
const int N=1.1e5+5;
int rd(){return rand()*rand()+1;}
using namespace std;
//FHQ-Treap:
int n,m,cnt,rt,q;
struct FHQ_Treap{
    struct Tree{
        int ls,rs,val,siz,rnd;
    }t[N];
    void pushup(int x){t[x].siz=t[t[x].ls].siz+t[t[x].rs].siz+1;}
    int Node()
    {
        cnt++;
        t[cnt]={0,0,cnt,1,rd()};
        return cnt;
    }
    void splite(int x,int &a,int &b,int k)
    {
        if(!x){a=b=0;return;}
        int tmp=t[t[x].ls].siz+1;
        if(tmp<=k)
        {
            a=x;
            splite(t[x].rs,t[a].rs,b,k-tmp);
            pushup(a);
        }
        else
        {
            b=x;
            splite(t[x].ls,a,t[b].ls,k);
            pushup(b);
        }
    }
    int merge(int x,int y)
    {
        if(!x||!y)return x|y;
        if(t[x].rnd<t[y].rnd)
        {
            t[x].rs=merge(t[x].rs,y);
            pushup(x);
            return x;
        }
        else
        {
            t[y].ls=merge(x,t[y].ls);
            pushup(y);
            return y;
        }
    }
}T;
string s[N];
void work()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>s[i];
        rt=T.merge(rt,T.Node());
    }
    cin>>m;
    for(int i=1,k,a,b;i<=m;i++)
    {
        cin>>s[T.Node()];
        cin>>k;
        T.splite(rt,a,b,k);
        rt=T.merge(T.merge(a,cnt),b);
    }
    cin>>q;
    for(int i=1,k,a,b,c;i<=q;i++)
    {
        cin>>k;
        T.splite(rt,a,b,k+1);
        T.splite(a,a,c,k);
        cout<<s[T.t[c].val]<<"\n";
        rt=T.merge(T.merge(a,c),b);
    }
}
int main()
{
    //freopen("P3850.in","r",stdin);freopen("P3850.out","w",stdout);
	ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    work();
    return 0;
}
posted @ 2025-01-07 18:52  liuboom  阅读(12)  评论(0)    收藏  举报