hdu 1754 splay tree伸展树 初战(单点更新,区间属性查询)

题意:与区间查询点更新,点有20W个,询问区间的最大值。曾经用线段树,1000+ms,今天的伸展树,890没ms,差不多。

第一次学习伸展树,一共花了2个单位时间,感觉伸展树真很有用,也很好玩。现在只学了一点点。切个点更新试试。

大致思路:用编号(数组)作为树的键值建树,每插一个数,沿路节点更新最大值(每个结点有一个附加信息标记以之为子树的树所有点的最大值)。所以,查询时【i,j】,只要把i-1伸展到树根,把j+1伸展到I-1下面,那么j+1的左子树就是要的区间了!查该子树根值信息即可(特判端点)!同理,更新操作,只要把待更新的伸展到根,然后更新它,同时维护一下信息即可。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxx=200010;
int a[maxx];int child[maxx][2];int fa[maxx];int maxo[maxx];  //a[i]是原来数组值,child左右孩子(0,1),maxo【i】是以序号i为根的子树(包括自身)的最大值。
int root=0;
void inline maintain(int n)        //点被修改后,该点值的维护
{
    maxo[n]=maxo[n]>a[n]?maxo[n]:a[n];
}
void inline rotate(int x,int f)    //f=1右旋,f=0左旋
{
    int y=fa[x];
    maxo[x]=maxo[y];                  //最大值的更新
    maxo[y]=maxo[child[x][f]]>maxo[child[y][f]]?maxo[child[x][f]]:maxo[child[y][f]];
    maintain(y);

    child[y][!f]=child[x][f];            //三次的重连线,注意顺序。
    fa[child[x][f]]=y;

    if(fa[y])
    {
        if(y==child[fa[y]][0])
          child[fa[y]][0]=x;
        else
          child[fa[y]][1]=x;
    }
    else
    {
        root=x;
    }
    fa[x]=fa[y];

    child[x][f]=y;
    fa[y]=x;
}
void splay(int n,int goal)   //把序号为i的点转到点goal下面的孩子。
{
    while(fa[n]!=goal)    //一直左右旋即可
    {
        int y=fa[n];
        rotate(n,child[y][0]==n?1:0);
    }
}
void inline insert(int n) //插入来建树
{
    int temp=root;
    if(root==0)       //根节点
    {
        root=n;
        maxo[n]=n;
        return ;
    }
    else
    {
        while(1)
        {
            maxo[temp]=maxo[temp]<a[n]?a[n]:maxo[temp];//插入时候维护最大值
            if(n<temp)                       //左边
            {
                if(child[temp][0]==0)
                {
                    child[temp][0]=n;
                    fa[n]=temp;
                    maxo[n]=a[n];
                    splay(n,0);           //注意这里要伸展,否则建树就是一般的排序二叉树,会超时
                    return ;
                }
                temp=child[temp][0];
            }
            else                        //右边
            {
                if(child[temp][1]==0)
                {
                    child[temp][1]=n;
                    fa[n]=temp;
                    maxo[n]=a[n];
                     splay(n,0);
                    return ;
                }
                temp=child[temp][1];
            }
        }
    }
}
void update(int n,int x)  //更新 ,把序号为n的值更新为x
{
    splay(n,0);
    a[n]=x;
    maxo[n]=maxo[child[n][0]]>maxo[child[n][1]]?maxo[child[n][0]]:maxo[child[n][1]];
    maintain(n);
}
void clear()        //初始化
{
    root=0;
    for(int i=0;i<maxx;i++)
    {
        maxo[i]=child[i][0]=child[i][1]=fa[i]=0;
    }
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        clear();
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            insert(i);
        }
        char q;int i,j;
        while(m--)
        {
            getchar();
            scanf("%c%d%d",&q,&i,&j);
            if(q=='Q')
           {

               int ans=0;
               if(i==1&&j!=n)               //区间端点的特判
               {
                  splay(j+1,0);
                  ans=maxo[child[j+1][0]];
               }
               else if(i!=1&&j==n)
               {
                    splay(i-1,0);
                    ans=maxo[child[i-1][1]];
               }
               else if(i==1&&j==n)
               {
                    ans=maxo[root];
               }
               else
               {
                    splay(i-1,0);
                    splay(j+1,i-1);
                    ans=maxo[child[j+1][0]];
               }
              printf("%d\n",ans);
           }
          else
           {
            update(i,j);
           }
        }
    }
    return 0;
}

hdu 1754 splay tree伸展树 初战(单点更新,区间属性查询)

时间: 2024-10-05 13:57:00

hdu 1754 splay tree伸展树 初战(单点更新,区间属性查询)的相关文章

[转] Splay Tree(伸展树)

好久没写过了,比赛的时候就调了一个小时,差点悲剧,重新复习一下,觉得这个写的很不错.转自:here Splay Tree(伸展树) 二叉查找树(Binary Search Tree)能够支持多种动态集合操作.因此,在信息学竞赛中,二叉排序树起着非常重要的作用,它可以被用来表示有序集合.建立索引或优先队列等. 作用于二叉查找树上的基本操作的时间是与树的高度成正比的.对一个含n各节点的完全二叉树,这些操作的最坏情况运行时间为O(log n).但如果树是含n个节点的线性链,则这些操作的最坏情况运行时间

hdu 1166 敌兵布阵(线段树之 单点更新+区间求和)

敌兵布阵                                                                             Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵

HDU 3074-Multiply game(线段树:单点更新,区间求积)

Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1450    Accepted Submission(s): 508 Problem Description Tired of playing computer games, alpc23 is planning to play a game on numbe

HDU 1754 I Hate It(线段树,单点更新,线段查询)

这道题是线段树入门题,其问题是单点更新,线段查询. 这里本来还打算用lazy标记做一下,但是不行,必须更新到单点 #include <map> #include <set> #include <queue> #include <cmath> #include <cmath> #include <vector> #include <bitset> #include <vector> #include <cs

hdu 1754 I Hate It(线段树之 单点更新+区间最值)

I Hate It                                                                             Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description 非常多学校流行一种比較的习惯.老师们非常喜欢询问.从某某到某某其中,分数最高的是多少. 这让非常多学生非常反感. 无论你

HDU 1540 Tunnel Warfare 线段树:单点更新,区间合并

Tunnel Warfare                                  Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast

SPOJ - QTREE(树链剖分+单点更新+区间最大值查询)

题意:给出n个点n-1条边的树,有两个操作,一个是查询节点l到r的边的最大值,然后指定边的更改权值. 题解:差不多是树链剖分的模版题,注意每个点表示的边是连向其父亲节点的边. #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int M = 1e4 + 10; struct Edge { int v , next; }edge[M << 1]

hdu-1166-敌兵布阵-线段树-单点更新,区域查询

线段树的单点更新,区域查询操作. #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> using namespace std; #define lmin 1 #define rmax n #define lson l,(l+r)/2,rt<<1 #define rson (l+r)/2+1,r,rt&l

【HDU】1754 I hate it ——线段树 单点更新 区间最值

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 37448    Accepted Submission(s): 14816 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要