【codevs1343】[HNOI]蚱蜢

本文介绍了一种使用平衡树解决区间查询问题的方法,并提供了一个具体的实现案例。该案例涉及到了平衡树的基本操作,如插入、删除节点及区间最大值查询等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

= =鬼知道这是那年的HNOI题,连bzoj上都没有,其实就是维护一个平衡树就好了,然后区间查询,支持删点加点。
涉及区间操作注意在两旁添加结点后原数组的标号改动问题,这道题相对来说调的比较快

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>

using namespace std;
const int N=200010,inf=0x3f3f3f3f;
int n,m;
int sz,root;
int a[N],ch[N][2],size[N],key[N],mx[N],fa[N];
inline void clear(int x){ch[x][0]=ch[x][1]=size[x]=fa[x]=key[x]=0;}
inline void updata(int x)
{
    if (x)
    {
        size[x]=1;
        mx[x]=key[x];
        if (ch[x][0])
        {
            size[x]+=size[ch[x][0]];
            mx[x]=max(mx[x],mx[ch[x][0]]);
        }
        if (ch[x][1])
        {
            size[x]+=size[ch[x][1]];
            mx[x]=max(mx[x],mx[ch[x][1]]);
        }
    }
}
inline int get(int x){return ch[fa[x]][1]==x;}
inline void rotate(int x)
{
    int old=fa[x],oldf=fa[old],which=get(x);
    ch[old][which]=ch[x][which^1],fa[ch[old][which]]=old;
    ch[x][which^1]=old;fa[old]=x;fa[x]=oldf;
    if (oldf)ch[oldf][ch[oldf][1]==old]=x;
    updata(old);updata(x);
}
inline void splay(int x,int tar)
{
    for (int old;(old=fa[x])!=tar;rotate(x))
    if (fa[old]!=tar)rotate(get(x)==get(old)?old:x);
    if (!tar)root=x;
}
inline int build(int l,int r,int old)
{
    if (l>r)return 0;
    int now=++sz;
    int mid=(l+r)>>1;
    key[now]=a[mid];mx[now]=a[mid],size[now]=1;fa[now]=old;
    ch[now][0]=build(l,mid-1,now);
    ch[now][1]=build(mid+1,r,now);
    updata(now);
    return now;
}
inline int find(int x)
{
    int now=root;
    while(1)
    {
        if (ch[now][0]&&x<=size[ch[now][0]])
        now=ch[now][0];
        else 
        {
            int temp=1;
            if (ch[now][0])
            temp+=size[ch[now][0]];
            if (x<=temp)return now;
            x-=temp;
            now=ch[now][1];
        }
    }
}
inline int findval(int x)
{
    int now=root;
    while(1)
    {
        if (ch[now][0]&&x<=size[ch[now][0]])now=ch[now][0];
        else 
        {
            int temp=1;
            if (ch[now][0])
            temp+=size[ch[now][0]];
            if (x<=temp)return key[now];
            x-=temp;now=ch[now][1];
        }
    }
}
inline void query(int l,int r)
//L-1,R+1
{
    int aa=find(l);
    int bb=find(r+2);
    splay(aa,0);
    splay(bb,aa);
    int ans=mx[ch[ch[root][1]][0]];
    printf("%d\n",ans);
    updata(ch[root][1]);
    updata(root);
}
inline void insert(int x,int val)
{
    int aa=find(x);
    int bb=find(x+1);
    splay(aa,0);
    splay(bb,aa);
    ch[ch[root][1]][0]=++sz;
    fa[sz]=ch[root][1];
    ch[sz][0]=ch[sz][1]=0;
    key[sz]=val;mx[sz]=val;
    size[sz]=1;updata(fa[sz]);
    updata(root);
}
inline void del(int x)
{
    int aa=find(x);
    int bb=find(x+2);
    splay(aa,0);
    splay(bb,aa);
    ch[ch[root][1]][0]=0;
    updata(ch[root][1]);
    updata(root);
}
int main()
{
    int st,cnt;
    scanf("%d%d",&n,&m);
    a[1]=-inf,a[n+2]=inf;
    for (int i=1;i<=n;++i)
    scanf("%d",&a[i+1]);
    root=build(1,n+2,0);
    for (int i=1;i<=m;++i)
    {   
        scanf("%d",&st);
        char c=getchar();
        while(c!='L'&&c!='D')c=getchar();
        scanf("%d",&cnt);
        if (c=='L')
        {   
            int L=st-cnt;
            int R=st-1;
            query(L,R);
            int val=findval(st+1);
            del(st);
            insert(L,val);
        }   
        else 
        {
            int L=st+1;
            int R=st+cnt;
            query(L,R);
            int val=findval(st+1);
            del(st);
            insert(R,val);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值