【JSOI2007】动态最值 Splay

来源:互联网 发布:五笔for mac 编辑:程序博客网 时间:2024/05/18 20:04

题目描述

    有一个包含n个元素的数组,要求实现以下操作:
  DELETE k :删除位置k上的数。右边的数往左移一个位置。
  QUERY i j :查询位置i~j上所有数的最小值和最大值。
  例如有10个元素:
这里写图片描述
  QUERY 2 8的结果为2 9。依次执行DELETE 3和DELETE 6(注意这时删除的是原始数组的元素7)后数组变为:
  这里写图片描述
  QUERY 2 8的结果为1 7。

题目大意

删数,求区间最大最小值。

数据范围

1≤n, m≤10^6 数字绝对值小于10^9

样例输入

10 4
1 5 2 6 7 4 9 3 1 5
2 2 8
1 3
1 6
2 2 8

样例输出

2 9
1 7

解题思路

Splay

代码

注意常数巨大,scanf都会超时一组。

#include <bits/stdc++.h>#define Maxn 1000005using namespace std;inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}int a[Maxn],n;struct splay{    int f[Maxn],son[Maxn][2],size[Maxn],vl[Maxn],Max[Maxn],Min[Maxn],root;    void PushUp(int x){        if(!x)return;        size[x]=size[son[x][0]]+size[son[x][1]]+1;        Max[x]=max(max(Max[son[x][0]],Max[son[x][1]]),(x==1||x==n+2?-1<<30:vl[x]));        Min[x]=min(min(Min[son[x][0]],Min[son[x][1]]),(x==1||x==n+2?1<<30:vl[x]));    }    void Rotate(int x){        int fa=f[x],gr=f[fa],s=son[fa][1]==x,sn=son[x][!s];        son[f[x]=gr][son[gr][1]==fa]=x;        son[f[sn]=fa][s]=sn;        son[f[fa]=x][!s]=fa;        PushUp(sn);        PushUp(fa);        PushUp(x);    }    void Splay(int x,int goal){        if(x==goal)return;        while(f[x]!=goal){            if(f[f[x]]!=goal&&(son[f[f[x]]][1]==f[x])==(son[f[x]][1]==x))Rotate(f[x]);            Rotate(x);        }        if(!goal)root=x;    }    int Select(int pos){        if(!pos)return 0;        int p=root;        while(size[son[p][0]]+1!=pos){            if(pos<=size[son[p][0]])p=son[p][0];            else pos-=size[son[p][0]]+1,p=son[p][1];        }        return p;    }    void Delete(int pos){        int u=Select(pos),v=Select(pos+2);        Splay(u,0);        Splay(v,u);        size[son[v][0]]=0;        f[son[v][0]]=0;        son[v][0]=0;        PushUp(v);        PushUp(u);    }    void Build(int L,int r,int fa){        if(L>r)return;        int mid=(L+r)/2;        if(L==r){            Min[mid]=Max[mid]=vl[mid]=a[mid-1];            size[mid]=1;        }else Build(L,mid-1,mid),Build(mid+1,r,mid);        vl[mid]=a[mid-1];        f[mid]=fa;        PushUp(mid);        son[fa][mid>=fa]=mid;    }    void Solve(int L,int r){        int u=Select(L),v=Select(r+2);        Splay(u,0);        Splay(v,u);        cout<<Min[son[v][0]]<<" "<<Max[son[v][0]]<<"\n";    }    void Init(int n){        Min[n+1]=Min[0]=1<<30;        Max[n+1]=Max[0]=-1<<30;        Build(1,n+2,0);        root=n+3>>1;    }}Solver;int main(){    n=Getint();    int m=Getint();    for(int i=1;i<=n;i++)a[i]=Getint();    Solver.Init(n);    while(m--){        int op=Getint();        if(op==1)Solver.Delete(Getint());        else{            int L=Getint(),r=Getint();            Solver.Solve(L,r);        }    }    return 0;}

附我们学校OJ里超时的result
这里写图片描述

0 0
原创粉丝点击