线段树套Splay求调 玄关
查看原帖
线段树套Splay求调 玄关
753757
paradise520楼主2024/7/1 09:47

样例过不了qwq 救救孩子

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=15000010,INF=2147483647;
int n,m,op,a,b,k,pos,idx;
int L[N],R[N],T[N];//Segment tree 
int w[N];
struct node
{
    int val,p,s[2];
    int sz,cnt;
}tr[N];// bst 

inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}

inline void pushup(int u)
{
    tr[u].sz=tr[tr[u].s[0]].sz+tr[tr[u].s[1]].sz+tr[u].cnt;
}

void add(int u,int v,int p)
{
	tr[u].sz=tr[u].cnt=1;
	tr[u].val=v,tr[u].p=p;
}

inline void rotate(int x)
{
    int y=tr[x].p,z=tr[y].p;
    int k= (tr[y].s[1]==x);
    tr[tr[x].s[k^1]].p=y,tr[y].s[k]=tr[x].s[k^1];
    tr[y].p=x,tr[x].s[k^1]=y;
    tr[x].p=z,tr[z].s[y==tr[z].s[1]]=x;
    pushup(y),pushup(x);
}

inline void splay(int &root,int x,int k)
{
	while(tr[x].p!=k)
	{
		int y=tr[x].p,z=tr[y].p;
		if(z!=k)
			if((x==tr[y].s[1])^(y==tr[z].s[1]))rotate(x);
			else rotate(y);
		rotate(x);
	}
	if(!k)root=x;
}

inline int find(int &root,int x)//找到val=x的节点
{
	int u=root;
	while(u&&tr[u].val!=x)
	{
		u=tr[u].s[x>tr[u].val];
	}
	return u;
}

void insert(int &root,int v)//平衡树插入 
{
	int u=root,p=0;
	while(u&&tr[u].val!=v)
	{
		p=u,u=tr[u].s[v>tr[u].val];
	}
	if(u)tr[u].cnt++;
	else
	{
		u=++idx;
		if(p)tr[p].s[v>tr[p].val]=u;
		add(u,v,p);
	}
	pushup(u);
	splay(root,u,0);
	return;
}

int get_prev(int &root,int x)//平衡树前驱 
{
	int k=find(root,x);splay(root,k,0);
	int u=tr[root].s[0];
	while(tr[u].s[1])u=tr[u].s[1];
	return u;
}

int get_next(int &root,int x)//平衡树后继 
{
	int k=find(root,x);splay(root,k,0);
	int u=tr[root].s[1];
	while(tr[u].s[0])u=tr[u].s[0];
	return u;
}

void remove(int &root,int x)//平衡树删除 
{
	int k=find(root,x);splay(root,k,0);
	if(tr[k].cnt>1)
	{
		tr[k].cnt--;
		pushup(k);
		return;
	}
	int l=get_prev(root,x),r=get_next(root,x);
	splay(root,l,0),splay(root,r,l);
	tr[r].s[0]=0;
	pushup(r),pushup(l);
	return;
}

int get_rank(int &root,int k)//平衡树查找排名
{
	int u=root,ans=0;
	while(u)
	{
		if(tr[u].val>k)u=tr[u].s[0];
		else
		{
			ans+=tr[tr[u].s[0]].sz;
			if(tr[u].val==k)
			{
				splay(root,u,0);
				return ans;
			}
			ans+=tr[u].cnt;
			u=tr[u].s[1];
		}
	}
	return ans;
}

void build(int u,int l,int r)//线段树建树 
{
    L[u]=l,R[u]=r;
    insert(T[u],INF),insert(T[u],-INF);
    for(int i=l;i<=r;i++)
        insert(T[u],w[i]);
    if(l==r)return;
    int mid=l+r>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
}

int query(int u,int l,int r,int k)//查询排名
{
    if(L[u]>=l&&R[u]<=r)return get_rank(T[u],k);
    int mid=L[u]+R[u]>>1,res=0;
    if(l<=mid)res+=query(u<<1,l,r,k);
    if(r>mid)res+=query(u<<1|1,l,r,k);
    return res;
}

void change(int u,int p,int k)//修改 
{
    remove(T[u],w[p]),insert(T[u],k);
    if(L[u]==R[u])return;
    int mid=L[u]+R[u]>>1;
    if(p<=mid)change(u<<1,p,k);
    else change(u<<1|1,p,k);
}

int get_prefix(int u,int l,int r,int x)
{
	if(L[u]>=l&&R[u]<=r)return tr[get_prev(T[u],x)].val;
	int res=-INF,mid=L[u]+R[u]>>1;
	if(l<=mid)res=max(res,get_prefix(u<<1,l,r,x));
	if(r>mid)res=max(res,get_prefix(u<<1|1,l,r,x));
	return res;
}

int get_suffix(int u,int l,int r,int x)
{
	if(L[u]>=l&&R[u]<=r)return tr[get_next(T[u],x)].val;
	int res=INF,mid=L[u]+R[u]>>1;
	if(l<=mid)res=min(res,get_suffix(u<<1,l,r,x));
	if(r>mid)res=min(res,get_suffix(u<<1|1,l,r,x));
	return res;
}

//void print_tree(int u)
//{
//	if(tr[u].s[0])print_tree(tr[u].s[0]);
//	printf("%d(*%d) ",tr[u].val,tr[u].cnt);
//	if(tr[u].s[1])print_tree(tr[u].s[1]);
//}

//void print()
//{
//	for(int i=1;i<=7;i++)
//   	printf("l=%d,r=%d\n",L[i],R[i]),print_tree(T[i]),puts("");
//    puts("");
//}

int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        w[i]=read();
    build(1,1,n);
    while(m--)
    {
    	print();
        op=read();
        switch(op)
        {
            case 1:
            {
                a=read(),b=read(),k=read();
                printf("%d\n",query(1,a,b,k)+1);
                break;
            }
            case 2:
            {
                a=read(),b=read(),k=read();
                int l=0,r=1e8;
                while(l<r)
                {
                    int mid=l+r+1>>1;
                    if(query(1,a,b,mid)+1<=k)l=mid;
                    else r=mid-1;
                }
                printf("%d\n",r);
                break;
            }
            case 3:
            {
                pos=read(),k=read();
                change(1,pos,k);
                w[pos]=k;
                break;
            }
            case 4:
            {
                a=read(),b=read(),k=read();
                printf("%d\n",get_prefix(1,a,b,k));
                break;
            }
            case 5:
            {
                a=read(),b=read(),k=read();
                printf("%d\n",get_suffix(1,a,b,k));
                break; 
            }
            default:
            {
                puts("input_error");
                break;
            }
        }
    }
    return 0;
}
2024/7/1 09:47
加载中...