[vijos1081]野生动物园(splay)

来源:互联网 发布:centos搭建网站 编辑:程序博客网 时间:2024/04/29 11:25

题目描述

传送门

题解

这道题是主席树裸题啊对不对,为什么要放到平衡树分类里叻?
因为这道题有一个非常特殊的性质:区间不互相包含。
那就是说,如果将区间排序的话,左端点和右端点都是单调的。
那么就可以维护一个平衡树每次查询第k大值就行了,时间复杂度O(2nlogn+mlogn)

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define N 100005#define inf 1000000000int n,m,root,sz;int a[N],f[N],ch[N][2],size[N],key[N],num[N],ans[N];struct hp{int l,r,k,id;}q[N];int cmp(hp a,hp b){    return a.l<b.l||(a.l==b.l&&a.r<b.r);}void clear(int x){    f[x]=ch[x][0]=ch[x][1]=size[x]=key[x]=0;}int get(int x){    return ch[f[x]][1]==x;}void update(int x){    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}void rotate(int x){    int old=f[x],oldf=f[old],wh=get(x);    ch[old][wh]=ch[x][wh^1];    f[ch[old][wh]]=old;    ch[x][wh^1]=old;    f[old]=x;    if (oldf) ch[oldf][ch[oldf][1]==old]=x;    f[x]=oldf;    update(old);    update(x);}void splay(int x){    for (int fa;fa=f[x];rotate(x))        if (f[fa])            rotate( (get(x)==get(fa))?fa:x );    root=x;}void insert(int x){    if (!root)    {        root=++sz;        size[sz]=1;        key[sz]=x;        return;    }    int now=root,fa=0;    while (1)    {        fa=now;        now=ch[now][x>key[now]];        if (!now)        {            ++sz;            f[sz]=fa;ch[fa][x>key[fa]]=sz;            size[sz]=1;key[sz]=x;            splay(sz);            return;        }    }}int pre(){    int now=ch[root][0];    while (ch[now][1]) now=ch[now][1];    return now;}void del(int x){    splay(x);    if (!ch[root][0]&&!ch[root][1])    {        clear(root);        root=0;        return;    }    if (!ch[root][0])    {        int oldroot=root;        root=ch[oldroot][1];        f[root]=0;        clear(oldroot);        return;    }    if (!ch[root][1])    {        int oldroot=root;        root=ch[oldroot][0];        f[root]=0;        clear(oldroot);        return;    }    int oldroot=root;    int leftbig=pre();splay(leftbig);    ch[root][1]=ch[oldroot][1];    f[ch[root][1]]=root;    update(root);    clear(oldroot);    return;}int find(int x){    int now=root;    while (1)    {        if (x<=size[ch[now][0]]) now=ch[now][0];        else        {            x-=size[ch[now][0]];            if (x==1) return key[now];            --x;            now=ch[now][1];        }    }}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=n;++i) scanf("%d",&a[i]);    for (int i=1;i<=m;++i) scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k),q[i].id=i;    sort(q+1,q+m+1,cmp);    for (int i=q[1].l;i<=q[1].r;++i) insert(a[i]),num[i]=sz;    ans[q[1].id]=find(q[1].k);    for (int i=2;i<=m;++i)    {        for (int j=q[i-1].r+1;j<=q[i].r;++j) insert(a[j]),num[j]=sz;        for (int j=q[i-1].l;j<q[i].l;++j) del(num[j]);        ans[q[i].id]=find(q[i].k);    }    for (int i=1;i<=m;++i) printf("%d\n",ans[i]);    return 0;}
0 0
原创粉丝点击