[bzoj4864]神秘物质

题目描述

这里写图片描述

裸题

容易观察最小是在相邻差间取最小
最大直接就是最大减最小
那些加加删删的splay维护一下就好了

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;
const int maxn=100000+10,inf=2000000000;
int key[maxn*2],val[maxn*2],size[maxn*2],mx[maxn*2],mi[maxn*2],num[maxn*2],father[maxn*2],tree[maxn*2][2];
int sta[80];
int i,j,k,u,v,w,l,r,t,n,m,tot,top,root,ans;
char ch;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
char get(){
    char ch=getchar();
    while (ch!='m'&&ch!='e'&&ch!='i'&&ch!='n'&&ch!='a') ch=getchar();
    return ch;
}
int pd(int x){
    return tree[father[x]][1]==x;
}
void update(int x){
    num[x]=val[x];
    mx[x]=mi[x]=key[x];
    if (tree[x][0]){
        num[x]=min(num[x],num[tree[x][0]]);
        mx[x]=max(mx[x],mx[tree[x][0]]);
        mi[x]=min(mi[x],mi[tree[x][0]]);
    }
    if (tree[x][1]){
        num[x]=min(num[x],num[tree[x][1]]);
        mx[x]=max(mx[x],mx[tree[x][1]]);
        mi[x]=min(mi[x],mi[tree[x][1]]);
    }
    size[x]=size[tree[x][0]]+size[tree[x][1]]+1;
}
void rotate(int x){
    int y=father[x],z=pd(x);
    father[x]=father[y];
    if (father[y]) tree[father[y]][pd(y)]=x;
    tree[y][z]=tree[x][1-z];
    if (tree[x][1-z]) father[tree[x][1-z]]=y;
    tree[x][1-z]=y;
    father[y]=x;
    update(y);
    update(x);
    if (root==y) root=x;
}
void splay(int x,int y){
    while (father[x]!=y){
        if (father[father[x]]!=y)
            if (pd(x)==pd(father[x])) rotate(father[x]);else rotate(x);
        rotate(x);
    }
}
int kth(int x,int y){
    if (size[tree[x][0]]+1==y) return x;
    else if (size[tree[x][0]]+1>y) return kth(tree[x][0],y);
    else return kth(tree[x][1],y-size[tree[x][0]]-1);
}
void write(int x){
    if (!x){
        putchar('0');
        putchar('\n');
        return;
    }
    top=0;
    while (x){
        sta[++top]=x%10;
        x/=10;
    }
    while (top) putchar('0'+sta[top--]);
    putchar('\n');
}
int main(){
    //freopen("data.in","r",stdin);freopen("data.out","w",stdout);
    n=read();m=read();
    tot=n;
    fo(i,1,n){
        key[i]=read();
        if (i>1) val[i]=abs(key[i]-key[i-1]);else val[i]=inf;
    }
    fd(i,n,1){
        update(i);
        father[i]=i-1;
        if (i>1) tree[i-1][1]=i;
    }
    root=1;
    while (m--){
        ch=get();
        if (ch=='m'){
            ch=get();
            if (ch=='e'){
                j=read();k=read();
                u=kth(root,j);
                splay(u,0);
                v=kth(tree[u][1],1);
                splay(v,u);
                if (tree[v][1]){
                    w=kth(tree[v][1],1);
                    splay(w,v);
                    val[w]=abs(key[w]-k);
                    update(w);
                }
                tree[u][1]=tree[v][1];
                if (tree[v][1]) father[tree[v][1]]=u;
                key[u]=k;
                if (tree[u][0]){
                    w=kth(tree[u][0],size[tree[u][0]]);
                    splay(w,u);
                    val[u]=abs(key[w]-key[u]);
                }
                else val[u]=inf;
                update(u);
            }
            else if (ch=='i'){
                l=read();r=read();
                u=kth(root,r);
                splay(u,0);
                if (l+1==r){
                    write(val[u]);
                    continue;
                }
                v=kth(tree[u][0],l+1);
                splay(v,u);
                ans=val[u];
                ans=min(ans,val[v]);
                if (tree[v][1]) ans=min(ans,num[tree[v][1]]);
                write(ans);
            }
            else{
                l=read();r=read();
                u=kth(root,r);
                splay(u,0);
                v=kth(tree[u][0],l);
                splay(v,u);
                j=k=key[u];
                j=max(j,key[v]);
                k=min(k,key[v]);
                if (tree[v][1]){
                    j=max(j,mx[tree[v][1]]);
                    k=min(k,mi[tree[v][1]]);
                }
                write(j-k);
            }
        }
        else{
            j=read();k=read();
            u=kth(root,j);
            splay(u,0);
            key[++tot]=k;
            if (tree[u][1]){
                v=kth(tree[u][1],1);
                splay(v,u);
                val[v]=abs(key[v]-k);
                update(v);
            }
            if (tree[u][1]) father[tree[u][1]]=tot;
            tree[tot][1]=tree[u][1];
            tree[u][1]=tot;
            father[tot]=u;
            val[tot]=abs(key[u]-k);
            update(tot);
            update(u);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值