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

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

很对劲的太刀流->

题意非常简单,就是维护一个数据结构,支持区间排名、区间第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('\n');return;}
    if(x<0){putchar('-');x=-x;}
    while(x)ch[++f]=x%10+'0',x/=10;
    while(f)putchar(ch[f--]);
    putchar('\n');
}
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了。

据说拼命卡常能过。

posted @ 2018-03-19 21:04  echo6342  阅读(296)  评论(0编辑  收藏  举报