LibreOJ #107. 维护全序集

                        内存限制:256 MiB 时间限制:1000 ms 标准输入输出

                            题目类型:传统 评测方式:文本比较

                                上传者: 匿名

splay模板题

屠龙宝刀点击就送

#include <cstdio>
typedef long long LL;
#define N 300500

LL data[N];
int siz[N],cnt[N],ch[N][2],fa[N],root,cn,n;
inline int son(int x) {return ch[fa[x]][1]==x;}
inline void pushup(int rt)
{
    int l=ch[rt][0],r=ch[rt][1];
    siz[rt]=cnt[rt]+siz[l]+siz[r];
}
inline void rotate(int x)
{
    int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
    if(z) ch[z][c]=x;
    else root=x;
    fa[x]=z;
    if(a) fa[a]=y;
    ch[y][b]=a;
    ch[x][!b]=y;
    fa[y]=x;
    pushup(y);
    pushup(x);
}
void splay(int x,int i)
{
    for(;fa[x]!=i;)
    {
        int y=fa[x],z=fa[y];
        if(z==i) rotate(x);
        else
        {
            if(son(x)==son(y))
            {
                rotate(y);
                rotate(x);
            }
            else
            {
                rotate(x);
                rotate(x);
            }
        }
    }
}
void ins(int &rt,LL x)
{
    if(!rt)
    {
        rt=++cn;
        data[cn]=x;
        siz[cn]=cnt[cn]=1;
        splay(cn,0);
        return;
    }
    if(data[rt]==x)
    {
        cnt[rt]++;
        siz[rt]++;
        splay(rt,0);
        return;
    }
    if(x<data[rt])
    {
        ins(ch[rt][0],x);
        fa[ch[rt][0]]=rt;
        pushup(rt);
    }
    else
    {
        ins(ch[rt][1],x);
        fa[ch[rt][1]]=rt;
        pushup(rt);
    }
}
int getmn(int rt)
{
    int p=rt,ans=-1;
    for(;p;p=ch[p][0]) ans=p;
    return ans;
}
void del(int rt,LL x)
{
    if(data[rt]==x)
    {
        if(cnt[rt]>1)
        {
            cnt[rt]--;
            siz[rt]--;
        }
        else
        {
            splay(rt,0);
            int p=getmn(ch[rt][1]);
            if(p!=-1)
            {
                splay(p,rt);
                root=p;
                fa[p]=0;
                ch[p][0]=ch[rt][0];
                fa[ch[rt][0]]=p;
            }
            else
            {
                root=ch[rt][0];
                fa[ch[rt][0]]=0;
            }
        }
        return;
    }
    if(x<data[rt])
    {
        del(ch[rt][0],x);
        pushup(rt);
    }
    else
    {
        del(ch[rt][1],x);
        pushup(rt);
    }
}
int getkth(int rt,int k)
{
    int l=ch[rt][0];
    if(siz[l]+1<=k&&k<=siz[l]+cnt[rt]) return rt;
    if(siz[l]+1>k) return getkth(ch[rt][0],k);
    else if(k>siz[l]+cnt[rt]) return getkth(ch[rt][1],k-(siz[l]+cnt[rt]));
}
int get_suc(int rt,LL x)
{
    int p=rt,ret=-1;
    for(;p;)
    {
        if(x>=data[p]) p=ch[p][1];
        else
        {
            ret=p;
            p=ch[p][0];
        }
    }
    return ret;
}
int get_pre(int rt,LL x)
{
    int p=rt,ret=-1;
    for(;p;)
    {
        if(x<=data[p]) p=ch[p][0];
        else
        {
            ret=p;
            p=ch[p][1];
        }
    }
    return ret;
}
int get_pos(int rt,LL x)
{
    if(data[rt]==x) return rt;
    if(x<data[rt]) return get_pos(ch[rt][0],x);
    else return get_pos(ch[rt][1],x);
}
int Main()
{
    scanf("%d",&n);
    for(LL opt,x,pos,flag;n--;)
    {
        scanf("%lld%lld",&opt,&x);
        if(!opt) ins(root,x);
        else if(opt==1) del(root,x);
        else if(opt==2) printf("%lld\n",data[getkth(root,x)]);
        else if(opt==3) ins(root,x),pos=get_pos(root,x),splay(pos,0),printf("%d\n",siz[ch[root][0]]),del(root,x);
        else if(opt==4) pos=get_pre(root,x),pos==-1?printf("-1\n"):printf("%lld\n",data[pos]);
        else pos=get_suc(root,x),pos==-1?printf("-1\n"):printf("%lld\n",data[pos]);
    }
    return 0;
}
int sb=Main();
int main(int argc,char *argv[]) {;}
时间: 2024-10-19 11:44:25

LibreOJ #107. 维护全序集的相关文章

小椛椛的板子们2

感觉前上一篇的内容有些太多了,剩下的放在这里吧. 小椛椛的板子们   <- 这是上一篇 二分图匹配 #include <cstdio> #include <iostream> #include <queue> #include <cstring> #define INF 1e9 #define rg register #define Max 100008 const int BUF = 12312313; char Buf[BUF], *buf = B

【GDKOI2016Day1T1-魔卡少女】【拆位】线段树维护区间内所有连续子区间的异或和

题意:给出N个数,M个操作.操作有修改和询问两种,每次修改将一个数改成另一个数,每次询问一个区间的所有连续子区间的异或和.n,m<=100000,ai<=1000 题解: 当年(其实也就是今年)做不出来的题..D1T1啊... 因为ai<=1000,我们可以拆位处理.拆成10个二进制位,每位开1棵线段树. 对于每个节点,维护: d:这段区间的异或和 L[0],L[1]:子区间一定从左端点开始,异或和为0,1的子区间分别有多少个 R[0],R[1]:子区间一定从右端点开始,异或和为0,1的

bzoj 1018 线段树维护连通性

本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护. 对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边构建起的连通性). 查询[l,r]时,先计算出[1,l-1],[l,r],[r+1,c]这三个线段的连通性,然后将[l,r]的四个角变成并查集的4个点,先用[l,r]中的6种关系更新,在看是否可以从左上角的点通过左边区间绕道左下角,以及从右上角通过右边区间绕道右下角,该并的并起来后直接看查询的点是否

[模板]洛谷T2042 NOI2005 维护数列 Splay

PS:某大佬讲,当心情特别好or特别不好的时候,可以来攻略这个题...果然萌新足足被这题恶心了半个月... 进入正题: 这道题题意如此之裸-Splayの究极进化,那么就没有什么好讲的,直接说搞法好了... 为了代码写起来方便,萌新封装得可能有些过,若不合诸位大佬的口味还请见谅~ 节点node结构体定义: key:节点原值:size:子树大小:ch[2]:子树指针: set_pd:记录是否打了MAKE-SAME的懒标记:setv:MAKE-SAME的修改值:turn:记录是否旋转: sum:子树元

2016shenyang-1002-HDU5893-List wants to travel-树链剖分+线段树维护不同区间段个数

肯定先无脑树链剖分,然后线段树维护一段区间不同个数,再维护一个左右端点的费用. 线段树更新,pushDown,pushUp的时候要注意考虑链接位置的费用是否相同 还有就是树链剖分操作的时候,维护上一个更新的位置的费用. 总之就是出现区间合并,就考虑总数是否要减一 好想不好写 //场上根本写不完啊 1 /*--------------------------------------------------------------------------------------*/ 2 3 #inc

bzoj 3669 lct维护最小生成树

大概题意:给一个无向图,有a,b两种边权,找一条从1到n的路径,使得max(a[i])+max(b[i])最小a[i],b[i]表示该路径上的边的对应权. 如果用类似最短路的DP来做,显然每个点的状态就必须是一个集合,保存的是一个下凸的点集,表示到达这个点的最小的a,b,这样肯定会挂,但该该种做法已经无法再优化或减少状态了. 考虑枚举其中一个权值b0,然后只考虑所有b权值小于等于b0的边,然后变成简单的问题,因为这个b0不满足二分三分之类的性质,所以肯定不能每次重建图,跑DP,最终的做法是从小到

bzoj1503 Splay 维护名次数,支持删除

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1503 题解: 维护一颗Splay和一个外部变量,树中每个节点表示一个人,节点权值a + 外部变量delta = 该员工工资. 细节看代码. 注意:一进来工资就低于最低工资的人不能算是“离开公司”的人. 1 #include <cstdio> 2 #define fprintf(...) 3 #define maxn 100100 4 5 struct Splay { 6 int key[m

Luogu P2023 [AHOI2009]维护序列

题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值. 输入输出格式 输入格式: 第一行两个整数N和P(1≤P≤1000000000).第二行含有N个非负整数,从左到右依次为 a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N).第三行有一个

bzoj 2453 : 维护队列 带修莫队

2453: 维护队列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 952  Solved: 432[Submit][Status][Discuss] Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你