这题Splay需要优化常数吗?T了4个点求助

P6136 【模板】普通平衡树(数据加强版)

y_kx_b @ 2022-07-21 20:48:10

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define gc std::getchar
int read(){int x=0;bool fh=1;char ch=gc();while(ch>'9'||ch<'0'){if(ch=='-')fh=0;
ch=gc();}while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=gc();return fh?x:-x;}
#define mem0(s) memset(s,0,sizeof s)
#define mem0x3f(s) memset(s,0x3f,sizeof s)
#define mem0xff(s) memset(s,0xff,sizeof s)
#define itn int
#define x first
#define y second
#if 0
#define int long long
#endif
using namespace std;
typedef pair<int,int>PII;
const int _=0,N=1919810;
namespace SPLAY//https://www.shuzhiduo.com/A/xl56emaxJr/
{
    int cnt[N],size[N],ch[N][2],val[N],fa[N],root=0,idx1=0;
    inline bool check(int x){return ch[fa[x]][1]==x;}
    inline void pushup(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];}
    #define rotate spin
    #define chk check
    void spin(int x)
    {
        itn y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1];
        ch[z][chk(y)]=x,fa[x]=z;
        ch[y][k]=w,fa[w]=y;
        ch[x][k^1]=y,fa[y]=x;
        pushup(y),pushup(x);
    }
    void splay(int x,int goal=0)
    {
        int y=fa[x];
        while(y!=goal){
            if(fa[y]!=goal)chk(x)^chk(y)?/*不在一条链上*/rotate(x):rotate(y);
            spin(x);
            y=fa[x];
        }
        if(!goal)root=x;
    }
    void find(int x)
    {
        if(!root)return;
        int cur=root;
        while(ch[cur][x>val[cur]]&&val[cur]!=x)
            cur=ch[cur][x>val[cur]];
        splay(cur);
    }
    void insert(int x)
    {
        int cur=root,p=root;
        while(val[cur]!=x&&cur)
            p=cur,cur=ch[cur][x>val[cur]];
        if(val[cur]==x)
            cnt[cur]++;
        else{
            cur=++idx1;
            if(p)ch[p][x>val[p]]=cur;
            ch[cur][0]=ch[cur][1]=0;
            size[cur]=cnt[cur]=1;
            val[cur]=x;fa[cur]=p;
        }
        splay(cur);
    }
    inline int rnk(int x)
    {
        find(x);
        return size[ch[root][0]]+1+(val[root]<x?cnt[root]:0);
    }
    int kth(int k)
    {
        itn cur=root;
        while(1){
            if(ch[cur][0]&&k<=size[ch[cur][0]])cur=ch[cur][0];
            else if(k>size[ch[cur][0]]+cnt[cur])
                k-=size[ch[cur][0]]+cnt[cur],cur=ch[cur][1];
            else return cur;
        }
    }
    int pre(int x)
    {
        find(x);
        if(val[root]<x)return root;
        int cur=ch[root][0],p=root;
        while(cur)
            p=cur,cur=ch[cur][1];
        return p;
    }
    int suc(int x)
    {
        find(x);
        if(val[root]>x)return root;
        int cur=ch[root][1],p=root;
        while(cur)
            p=cur,cur=ch[cur][0];
        return p;
    }
    void remove(int x)
    {
        int last=pre(x),next=suc(x);
        splay(last),splay(next,last);
        int tar=ch[next][0];
        if(cnt[tar]>1)cnt[tar]--/**/,pushup(tar),splay(tar);
        else ch[next][0]=0,size[next]--,size[last]--;
    }
    void main()
    {
        insert(0xcfcfcfcf);//-808464433
        insert(0x3f3f3f3f);
        size[1]=size[2]=cnt[1]=cnt[2]=0;
        int p=read();
        while(p--)
        {
            int op=read(),x=read();
            switch(op)
            {
                case 1:insert(x);break;
                case 2:remove(x);break;
                case 3:printf("%d\n",rnk(x));break;
                case 4:printf("%d\n",val[kth(x)]);break;
                case 5:printf("%d\n",val[pre(x)]);break;
                case 6:printf("%d\n",val[suc(x)]);break;
            }
        }
    }
    void P6136_main()
    {
        insert(0xffffffff),insert(0x7fffffff),size[1]=size[2]=cnt[1]=cnt[2]=0;
        int n=read(),m=read(),last=0,ans=0;
        while(n--)insert(read());
        while(m--){
            int op=read(),x=read()^last;
            switch(op){
                case 1:insert(x);break;
                case 2:remove(x);break;
                case 3:last=rnk(x);ans^=last;break;
                case 4:last=val[kth(x)];ans^=last;break;
                case 5:last=val[pre(x)];ans^=last;break;
                case 6:last=val[suc(x)];ans^=last;break;
            }
        }
        printf("%d\n",ans);
    }
}
int main(){SPLAY::P6136_main();return~~(0^_^0);}

by Iwara_qwq @ 2022-07-21 20:52:30

显然需要,splay常数挺大的


by y_kx_b @ 2022-07-21 20:56:02

@Lovable_xyz 所以是想方设法优化 Splay 的常数(但是我好像做不到)还是直接弃坑 Splay……?


by Carnival @ 2022-07-21 21:01:07

@y_kx_b 可是我的 Splay 没加什么卡常优化就过了啊。


by Iwara_qwq @ 2022-07-21 21:01:10

@y_kx_b 常数优化


by w23c3c3 @ 2022-07-21 21:05:10

kth 没 splay。


by y_kx_b @ 2022-07-21 21:16:37

@w23c3c3 所以 P3369终究还是数据水了……?


by w23c3c3 @ 2022-07-21 21:19:03

P3369 唯一有点用的 hack 只有 1,3 操作。


|