【GDOI2017模拟2.25】神秘物质

7 篇文章 0 订阅

Description

这里写图片描述

Input

这里写图片描述

Output

对于每个max和min输出结果

Sample Input

输入1:
4 3
5 8 10 2
max 1 3
min 1 3
max 2 4

输入2:
6 7
1 2 3 4 5 6
insert 1 3
max 2 4
merge 1 2
max 2 4
min 2 4
insert 6 1
max 5 7

Sample Output

输出1:
5
2
8

输出2:
1
2
1
5

Data Constraint

这里写图片描述

Solution

有加入删除和查询,一看就是splay
而且是近乎模板
splay左子树的在当前点的前面,右子树在当前点后面,需要维护的有:
当前区间的,数值最大值,数值最小值(这两个为了维护极差最大值),极差最大值
因为极差最小的两个数一定是连续的,所以:
区间的最左边的数,最右边的数(这两个为了维护极差最小值),极差最小值,
没有区间修改,所以打起来很简单
当模板练手

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 201000
#define INF 2147483647
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,fa[N],t[N][2],d[N],l[N],r[N],mx[N],mi[N],da[N],xi[N],size[N],tot,root;
int lr(int x){return x==t[fa[x]][1];}
void update(int x)
{
    mx[x]=max(max(mx[t[x][0]],mx[t[x][1]]),d[x]);
    if(d[x]!=0) mi[x]=d[x];else mi[x]=INF;
    if(t[x][0]) mi[x]=min(mi[x],mi[t[x][0]]);
    if(t[x][1]) mi[x]=min(mi[x],mi[t[x][1]]);
    if(t[x][0]) l[x]=l[t[x][0]];else l[x]=d[x];
    if(t[x][1]) r[x]=r[t[x][1]];else r[x]=d[x];
    da[x]=max(max(da[t[x][0]],da[t[x][1]]),mx[x]-mi[x]);
    xi[x]=INF;
    if(t[x][0]) xi[x]=min(min(abs(d[x]-r[t[x][0]]),xi[t[x][0]]),xi[x]);
    if(t[x][1]) xi[x]=min(min(abs(d[x]-l[t[x][1]]),xi[t[x][1]]),xi[x]);
    size[x]=size[t[x][0]]+size[t[x][1]]+1;
}
void rotate(int x)
{
    int y=fa[x],k=lr(x);
    t[y][k]=t[x][1-k];
    if(t[x][1-k]) fa[t[x][1-k]]=y;
    fa[x]=fa[y];
    if(fa[y]) t[fa[y]][lr(y)]=x;
    fa[y]=x;t[x][1-k]=y;
    update(y);update(x);
}
void splay(int x,int y)
{
    if(x==0) return;
    while(fa[x]!=y)
    {
        if(fa[fa[x]]!=y) 
            if(lr(x)==lr(fa[x])) rotate(fa[x]);
            else rotate(x);
        rotate(x);
    }
    if(y==0) root=x;
}
int kth(int x)
{
    int y=root;
    while(1)
    {
        if(x==size[t[y][0]]+1) return y;
        if(x>size[t[y][0]]+1) x=x-size[t[y][0]]-1,y=t[y][1];
        else y=t[y][0];
    }
    return y;
}
int main()
{
    scanf("%d%d\n",&n,&m);
    fa[1]=2;t[2][0]=1;
    size[1]=1;
    fo(i,2,n+1)
    {
        fa[i]=i+1;t[i+1][0]=i;
        scanf("%d",&d[i]);l[i]=r[i]=d[i];update(i);
    }
    tot=n+2;
    root=n+2;
    scanf("\n");
    splay(n/2,0);splay(n/4,0);
    for(;m;m--)
    {
        char ch;scanf("%c",&ch);scanf("%c",&ch);
        int x,y;
        if(ch=='e')
        {
            scanf("rge %d %d\n",&x,&y);
            int z=kth(x+2);
            x=kth(x+1);
            splay(x,0);splay(z,x);
            if(t[z][1]) fa[t[z][1]]=x,t[x][1]=t[z][1];
            d[x]=l[x]=r[x]=y;update(x);
        }
        if(ch=='n')
        {
            scanf("sert %d %d\n",&x,&y);
            int z=kth(x+2);
            x=kth(x+1);
            splay(x,0);splay(z,x);
            t[z][0]=++tot;fa[tot]=z;
            d[tot]=l[tot]=r[tot]=y;update(tot);update(z);update(x);
        }
        if(ch=='a')
        {
            scanf("x %d %d\n",&x,&y);
            x=kth(x);y=kth(y+2);
            splay(x,0);splay(y,x);
            printf("%d\n",da[t[t[root][1]][0]]);
        }
        if(ch=='i')
        {
            scanf("n %d %d\n",&x,&y);
            x=kth(x);y=kth(y+2);
            splay(x,0);splay(y,x);
            printf("%d\n",xi[t[t[root][1]][0]]);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值