zoukankan      html  css  js  c++  java
  • hdu1754(splay tree 单点更新,成段查询)

    题意就是简单的点更新,成段查询。

    splay tree 果真是常数比较大的log(n)操作。 比线段树还慢了这么多。

    //
    //  main.cpp
    //  splay
    //
    //  Created by 陈加寿 on 16/3/25.
    //  Copyright © 2016年 chenhuan001. All rights reserved.
    //
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    
    //来一发点更新,成段查询
    #define MAXN 1001000
    #define INF 1001000000
    
    struct Splay_Tree
    {
        int cnt, rt;
        struct node
        {
            int K,mxk;
            int key, size, fa, son[2];
            void set(int _key, int _size, int _fa,int _K)
            {
                mxk = K = _K;//这个表示这个节点的值
                key = _key;//这个为ID
                size=_size;
                fa=_fa;
                son[0]=son[1]=0;
            }
        }T[MAXN];
        inline void init()
        {
            cnt=0;
            T[cnt++].set(0, 0, 0, 0);//
            rt = 0;
            //初始化的时候,把0这个节点的K设置为INF
        }
        inline void PushUp(int x)
        {
            //这一步就很关键了
            T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+1;
            T[x].mxk = max(T[x].K,max(T[T[x].son[0]].mxk,T[T[x].son[1]].mxk));
        }
        
        inline void Rotate(int x, int p) //0左旋 1右旋
        {
            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);//先更新y
            PushUp(x);//再更新x
        }
        
        void Splay(int x, int To) //将x节点插入到To的子节点中
        {
            while(T[x].fa != To)
            {
                if(T[T[x].fa].fa == To)
                    Rotate(x, T[T[x].fa].son[0] == x);
                else
                {
                    int y=T[x].fa, z=T[y].fa;
                    int p=(T[z].son[0] == y);
                    if(T[y].son[p] == x)
                        Rotate(x, !p), Rotate(x, p); //之字旋
                    else
                        Rotate(y, p), Rotate(x, p); //一字旋
                }
            }
            if(To == 0) rt=x;
        }
        
        int find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处
        {
            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 prev() //返回比根值小的最大值 若无返回0 若有将其转移到根处
        {
            int x=T[rt].son[0];
            if(!x) return 0;
            while(T[x].son[1])
                x=T[x].son[1];
            Splay(x, 0);
            return x;
        }
        
        int next() //返回比根值大的最小值 若无返回0 若有将其转移到根处
        {
            int x=T[rt].son[1];
            if(!x) return 0;
            while(T[x].son[0])
                x=T[x].son[0];
            Splay(x, 0);
            return x;
        }
        
        void Insert(int key,int K) //插入key 并且将该节点转移到根处
        {
            if(!rt)
                T[rt = cnt++].set(key, 1, 0, K);
            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, K);
                T[y].son[key > T[y].key]=x;
                Splay(x, 0);
            }
        }
        
        void Delete(int key) //删除值为key的节点 若有重点只删其中一个 x的前驱移动到根处
        {
            int x=find(key);
            if(!x) 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 GetPth(int p) //获得第p小的节点 并将其转移到根处
        {
            if(!rt) return 0;
            int x=rt;
            while(x)
            {
                if(p == T[T[x].son[0]].size+1)
                    break;
                if(p>T[T[x].son[0]].size+1)
                {
                    p-=T[T[x].son[0]].size+1;
                    x=T[x].son[1];
                }
                else
                    x=T[x].son[0];
            }
            Splay(x, 0);
            return x;
        }
        
        int GetRank(int key) //获得值<=key的节点个数 并将其转移到根处 若<key只需将<=换为<
        {
            if(!rt) return 0;
            int x=rt, ret=0, y=0;
            while(x)
            {
                y=x;
                if(T[x].key <= key)
                {
                    ret+=T[T[x].son[0]].size+1;
                    x=T[x].son[1];
                }
                else
                    x=T[x].son[0];
            }
            Splay(y, 0);
            return ret;
        }
    }spt;
    
    int main() {
        //两种操作
        //一、修改某个节点值
        //二、区间查询
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            spt.init();
            for(int i=1;i<=n;i++)
            {
                int tmp;
                scanf("%d",&tmp);
                spt.Insert(i, tmp);
            }
            char sign;
            for(int i=0;i<m;i++)
            {
                getchar();
                int a,b;
                scanf("%c %d %d",&sign,&a,&b);
                if(sign == 'Q')
                {
                    if(a == b)
                    {
                        int id = spt.GetPth(a);
                        printf("%d
    ",spt.T[id].K);//区间只有一个点的时候
                        continue;
                    }
                    int idb = spt.GetPth(b);
                    int ida = spt.GetPth(a);
                    spt.Splay(idb, ida);
                    int idson = spt.T[idb].son[0];
                    int mx = max( spt.T[idson].mxk ,max(spt.T[ida].K,spt.T[idb].K));
                    printf("%d
    ",mx);
                }
                else
                {
                    //更新操作
                    int id = spt.GetPth(a);
                    spt.T[id].K = b;
                    spt.PushUp(id);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    关于数组赋值时找不到数组名字的问题
    显示转换与隐式转换
    类型(值类型和引用类型)
    .net webconfig中配置httphanlder无法生效的问题
    微信小程序开发知识点总结
    Raphael.js API 之 Element.attr()
    Raphael.js API 之 Element.attr()
    Raphael.js API之 Animation.delay(),Animation.repeat(),Element.animateWith()
    Raphael.js API之 Animation.delay(),Animation.repeat(),Element.animateWith()
    Raphael.js API之 Paper.path(),Element.click()
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5322562.html
Copyright © 2011-2022 走看看