• 并不对劲的线段树套平衡树


    最近很对劲的太刀流做的一道题中说树是无向连通无环图,并不对劲的片手流为了反驳他,决定与之针锋相对,就练线段无向连通无环图套平衡无向连通无环图的题。

    很对劲的太刀流->

    题意非常简单,就是维护一个数据结构,支持区间排名、区间第k大、单点修改、区间前驱后继这些操作。

    主席树+树状数组想必是可以做的,但是并不对劲的人并不想开权值线段树,于是就选择了这种常数极大的做法。

    需要注意的是,并不能直接找到区间内排在第k位的数。要二分出答案,然后判断解的排名是否对劲。答案是符合条件的的最大值(因为有的对劲的数并没有出现在数列里)。

    并不觉得有什么好说的。

    可以去洛谷的模板题提交-> 

    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define maxn 5000010
    #define ls son[u][0]
    #define rs son[u][1]
    #define rks son[rk][0]
    #define m (l+r>>1)
    #define s0 siz[0]=0
    #define Ls (n<<1)
    #define Rs (n<<1|1)
    #define inf 2147483647
    #define rep(i,x,y) for(register int i=(x);i<=(y);i++)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);i--)
    using namespace std;
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(isdigit(ch)==0 && ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(int x)
    {
        int f=0;char ch[20];
        if(!x){putchar('0'),putchar('
    ');return;}
        if(x<0){putchar('-');x=-x;}
        while(x)ch[++f]=x%10+'0',x/=10;
        while(f)putchar(ch[f--]);
        putchar('
    ');
    }
    int rt[maxn],fa[maxn],son[maxn][3],key[maxn],num[maxn],siz[maxn],a[maxn],cnt,nn,x,y,rank;
    inline void pu(int u){s0,siz[u]=siz[ls]+siz[rs]+num[u],s0;}
    inline int res(int k,int f){key[++cnt]=k,fa[cnt]=f,num[cnt]=1;return cnt;}
    inline int getso(int u){return son[fa[u]][0]!=u;}
    inline void rot(int u)
    {
        int fu=fa[u],ffu=fa[fu],l=getso(u),r=l^1,fl=getso(fu),rson=son[u][r];
        fa[rson]=fu,fa[u]=ffu,fa[fu]=u,son[u][r]=fu,son[fu][l]=rson,son[ffu][fl]=u;
        pu(fu),pu(u);
    }
    inline void splay(int u,int k,int pla)
    {
        while(fa[u]!=k){int fu=fa[u];if(fa[fu]!=k)rot(getso(u)^getso(fu)?u:fu);rot(u);}
        if(!k)rt[pla]=u;
    }
    inline void fnd(int k,int pla)
    {
        int u=rt[pla];
        while(son[u][k>key[u]]&&k!=key[u])u=son[u][k>key[u]];
        splay(u,0,pla);
    }
    inline int nxt(int k,int f,int pla)
    {
        fnd(k,pla);int u=rt[pla];
        if((key[u]>k&&f)||(key[u]<k&&!f))return u;
        u=son[u][f];
        while(son[u][f^1])u=son[u][f^1];
        return u;
    }
    inline void ins(int k,int pla)
    {
        int lk=nxt(k,0,pla),rk=nxt(k,1,pla);
        splay(lk,0,pla),splay(rk,lk,pla);
        if(rks)num[rks]++;
        else rks=res(k,rk);
        pu(rks),pu(rk),pu(lk);
    }
    inline void sgtr(int n,int l,int r)
    {
        rt[n]=res(-inf,0);
        son[rt[n]][1]=res(inf,rt[n]);
        pu(son[rt[n]][1]),pu(rt[n]);
        rep(i,l,r)ins(a[i],n);
        if(l==r)return;
        sgtr(Ls,l,m),sgtr(Rs,m+1,r);
    }
    inline int rnk(int k,int pla)
    {
        int u=rt[pla],rank=0;
        while(u)
        {
            if(key[u]==k){rank+=siz[ls];break;}
            if(key[u]<k)rank+=siz[ls]+num[u],u=rs;
            else u=ls;
        }
        return rank-1;
    }
    inline void del(int k,int pla)
    {
        int lk=nxt(k,0,pla),rk=nxt(k,1,pla);
        splay(lk,0,pla),splay(rk,lk,pla);
        if(num[rks]>1)num[rks]--;
        else rks=0;
        pu(rks),pu(rk),pu(lk);
    }
    inline int _1(int n,int l,int r,int k)
    {//getrank
        if(x<=l&&r<=y)return rnk(k,n);
        if(y<l||r<x)return 0;
        int lans=_1(Ls,l,m,k),rans=_1(Rs,m+1,r,k);
        return lans+rans;
    }
    inline int _2(int k)
    {//kth
        int l=0,r=100000001;
        while(l!=r)
        {
            rank=_1(1,1,nn,m)+1;
            if(rank>k) r=m;
            else l=m+1;
        }
        return l-1;
    }
    inline void _3(int n,int l,int r,int k)
    {//change
        if(x<l||r<x)return;
        del(a[x],n),ins(k,n);
        if(l==r)return;
        _3(Ls,l,m,k),_3(Rs,m+1,r,k);
        if(n==1)a[x]=k;
    }
    inline int _4(int n,int l,int r,int k)
    {//prefix
        if(x<=l&&r<=y)return key[nxt(k,0,n)];
        if(y<l||r<x)return -inf;
        int lans=_4(Ls,l,m,k),rans=_4(Rs,m+1,r,k);
        return max(lans,rans);
    }
    inline int _5(int n,int l,int r,int k)
    {//suffix
        if(x<=l&&r<=y)return key[nxt(k,1,n)];
        if(y<l||r<x)return inf;
        int lans=_5(Ls,l,m,k),rans=_5(Rs,m+1,r,k);
        return min(lans,rans);
    }
    int main()
    {
        int n,q,f,c;nn=n=read(),q=read();
        rep(i,1,n)a[i]=read();
        sgtr(1,1,n);
        while(q--)
        {
            f=read(),x=read(),y=read(),c;
            if(f==1)c=read(),write(_1(1,1,n,c)+1);
            if(f==2)c=read(),write(_2(c));
            if(f==3)_3(1,1,n,y);
            if(f==4)c=read(),write(_4(1,1,n,c));
            if(f==5)c=read(),write(_5(1,1,n,c));
        }
        return 0;
    }
    并不对劲

    不写splay这种常数极大的平衡无向连通无环图就不用开O2了。

    据说拼命卡常能过。

  • 相关阅读:
    (转)android res文件夹里面的drawable(ldpi、mdpi、hdpi、xhdpi、xxhdpi)
    ListView模拟微信好友功能
    最小生成树(普利姆算法、克鲁斯卡尔算法)
    Android Afinal框架学习(二) FinalActivity 一个IOC框架
    浅谈WebLogic和Tomcat
    变量定义和声明的差别(整理)
    浏览器内核分类
    设计模式 之 享元
    FPGA中浮点运算实现方法——定标
    兔子--Android中的五大布局
  • 原文地址:https://www.cnblogs.com/xzyf/p/8597700.html
Copyright © 2020-2023  润新知