poj 2761 feeding the dog (splay树 模板)

来源:互联网 发布:ecshop源码下载 编辑:程序博客网 时间:2024/04/30 12:10

题意:

    给你N个数,然后要你对下面M个查询回答:(L,R,K)。回答第L个数到第R个数之间的第K小数的值是多少。其中任意给定的两个区间[Li,Ri]和[Lj,Rj]之间不存在包含关系。

splay模板题,果然不是自己写的模板就是很多不了解的地方,调试起来贼鸡巴麻烦。
所有的真正的东西都存在结构体里面,查询返回的是离散化后的树上的节点次序。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cstdlib>#include <cmath>#include <utility>#include <vector>#include <queue>#include <map>#include <set>#define max(x,y) ((x)>(y)?(x):(y))#define min(x,y) ((x)>(y)?(y):(x))#define INF 0x3f3f3f3f#define MAXN 100005using namespace std;int cnt,rt;void init(){ cnt=1,rt=0;}int id[MAXN],res[MAXN];struct node{    int l,r,k;    int id;}s[MAXN];struct Tree{    int key,size,fa,son[2],num;    void set(int _key,int _size,int _fa,int _num)    {        key=_key;        size=_size;        fa=_fa;        son[0]=son[1]=0;        num=_num;    }}T[MAXN];int cmp(node a,node b){    if(a.l==b.l) return a.r>b.r;    else return a.l<b.l; } inline void PushUp(int x){    T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+1;}inline void Rotate(int x,int p){    int y=T[x].fa;    T[y].son[!p]=T[x].son[p];    T[T[x].son[p]].fa=y;    T[x].fa=T[y].fa;    if(T[x].fa)        T[T[x].fa].son[T[T[x].fa].son[1]==y]=x;    T[x].son[p]=y;    T[y].fa=x;    PushUp(y);    PushUp(x);}void Splay(int x,int To){    while(T[x].fa!=To) //直到父节点为To    {        if(T[T[x].fa].fa==To) //如果父节点的父节点==To 单旋            Rotate(x,T[T[x].fa].son[0]==x);        else //如果的父节点的父节点!=to 双旋        {            int y=T[x].fa,z=T[y].fa; //y是父节点,z是父节点的父节点            int p=(T[z].son[0]==y);//y是不是在父节点的0路线            if(T[y].son[p]==x)  //这里判断是不是和父节点所在路线相反            Rotate(x,!p),Rotate(x,p);// 如果相反 就是之字形            else                Rotate(y,p),Rotate(x,p);//相同 一字型        }    }    if(To==0) rt=x;}void Insert(int key,int num)//插入key 并且将该节点转移到根处{    if(!rt)        T[rt=cnt++].set(key,1,0,num);    else    {        int x=rt,y=0;        while(x)        {            y=x;            x=T[x].son[key>T[x].key];        }        T[x = cnt++].set(key,1,y,num);        T[y].son[key>T[y].key]=x;        Splay(x,0);    }}int find(int key){    int x=rt;    while(x&&T[x].key!=key)        x=T[x].son[key>T[x].key];    if(x) Splay(x,0);    return x;}int GetPth(int p)   //获得第p小的节点 并将其转移到根处{    if(!rt) return 0;    int x=rt,ret=0;    while(x)    {        if(p==T[T[x].son[0]].size+1)            break;        if(p>T[T[x].son[0]].size+1) //判断是第p个是在左边还是右边        {            p-=T[T[x].son[0]].size+1;            x=T[x].son[1];        }        else             x=T[x].son[0];    }    Splay(x,0);    return x;}void Delete(int key)//删除值为key的节点 若有重点只删其中一个 x的前驱移动到根处{    int x=find(key); //找到与key值相同的    if(!x) return ; //如果没有就return    int y=T[x].son[0];     while(T[y].son[1]) //找到左边叶子结点        y=T[y].son[1];    int z=T[x].son[1];  //找到右边叶子结点    while(T[z].son[0])        z=T[z].son[0];    if(!y&&!z)  //如果这是根结点    {        rt=0;        return ;    }    if(!y) //只有右叶子结点    {        Splay(z,0);        T[z].son[0]=0;        PushUp(z);        return ;    }    if(!z) //只有左叶子结点    {        Splay(y,0);        T[y].son[1]=0;        PushUp(y);        return ;    }    Splay(y,0);    Splay(z,y);    T[z].son[0]=0;    PushUp(z);    PushUp(y);}int main (){    int n,m;    while(scanf("%d%d", &n,&m)!=EOF)    {        init();        for(int i=1;i<=n;i++)        scanf("%d",&id[i]);        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&s[i].l,&s[i].r,&s[i].k);            s[i].id=i;        }        sort(s,s+m,cmp);        for(int i=s[0].l;i<=s[0].r;i++)        Insert(id[i],0);  //插入需要保留的值。第一个是优先级    //但是在插入后它会进行离散化。这个值会保存在结构体里面        res[s[0].id]=T[GetPth(s[0].k)].key;//由于有离散化 所以返回的是第k个节点        //通过结构体转回值        for(int i=1;i<m;i++)        {            for(int j=s[i-1].l;j<s[i].l;j++)            Delete(id[j]);//删除的是具体值,然后它会找在第几个节点上            if(s[i].r<s[i-1].r)            {                for(int j=s[i].r+1;j<=s[i-1].r;j++)                Delete(id[j]);            }            if(s[i].r>s[i-1].r)            {                for(int j=s[i-1].r+1;j<=s[i].r;j++)                {                    Insert(id[j],0);                }            }                res[s[i].id]=T[GetPth(s[i].k)].key;//由于有离散化 所以返回的是第k个节点        //通过结构体转回值        }        for(int i=0;i<m;i++)        printf("%d\n",res[i]);    }    return 0;}
0 0