HDU 1754区间最值 & SPLAY
真是亲切的1754啊。。第一道傻逼版的线段树做的是这个,后来学了zkw做的是这个,在后来决定打lrj线段树又打了一遍,如今再用splay和老朋友见面
从上到下依次为:加了读入优化的splay,splay,加了inline的splay,边读入边建树的lrj线段树,zkw线段树,以及线段树初体验
题意
单点修改询问区间最值。
SOL:
平衡树真是优美的植物,像陀螺通过不断的优雅的旋转体现自身的平衡与美感。
对于splay的区间问题,我们利用序号来建树,当要查询一个区间时,我们把这个区间左端点的前一个点旋到根,那么这个区间就都在根的右子树中,再将右端点的后一个点旋到根的右儿子,那么整段区间就都在根的右儿子的左儿子上了。整个过程利用BST的性质非常显然。当然为了防止越界我们把整段序列向右平移一格,便于维护。
对于这样的询问,splay与线段树没有什么区别,线段树是分割线段,而splay是取出线段,然后标记、最值、和什么的都一样了,所以线段树能实现的splay都能实现(除了可持久化。
当然对比上图,我们还是能看出它们之间的优劣。。zkw线段树继承了树状数组的优点,代码短效率高——但是貌似细节巨多。。我现在也忘得差不多了。。lrj线段树由于是nlgn的建树所以看起来稍微慢一点,实际上的效率应该在正常水平左右,打了一些注释所以代码长度显得长一些。 而splay。。。内存我多开了很多没有用的数组显得大一点。代码长度尽管以前没有用现在这么多的头文件。。但由于操作非常多尽管已经尽力把splay写得非常紧凑但还是要长处不少。
在速度上实现得和线段树差不多,看起来也挺好。
CODE:
/*==========================================================================
# Last modified: 2016-02-19 15:23
# Filename: hdu1754.cpp
# Description:
==========================================================================*/
#define me AcrossTheSky
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> #include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#define lowbit(x) (x)&(-x)
#define INF 1070000000
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define maxn 300000
#define getlc(a) ch[(a)][0]
#define getrc(a) ch[(a)][1]
using namespace std;
typedef long long ll;
typedef unsigned long long ull; template<class T> inline
void read(T& num) {
bool start=false,neg=false;
char c;
num=0;
while((c=getchar())!=EOF) {
if(c=='-') start=neg=true;
else if(c>='0' && c<='9') {
start=true;
num=num*10+c-'0';
} else if(start) break;
}
if(neg) num=-num;
}
/*==================split line==================*/
int root;
int n,m;
int fa[maxn],ch[maxn][2],_max[maxn],v[maxn],s[maxn],a[maxn];
int cnt=0;
int null;
inline void updata(int node){
s[node]=1+s[getlc(node)]+s[getrc(node)];
_max[node]=max(v[node],max(_max[getlc(node)],_max[getrc(node)]));
}
inline void rotate(int x){
int p=fa[x],q=fa[p],d=ch[p][1]==x;
fa[ch[p][d]=ch[x][d^1]]=p; updata(p);
fa[ch[x][d^1]=p]=x;
fa[x]=q;
if (q){
if (ch[q][0]==p) ch[q][0]=x;
else if (ch[q][1]==p) ch[q][1]=x;
}
updata(x);
}
inline void splay(int x,int &aim){
for(int y;(y=fa[x])!=aim;rotate(x))
if (fa[y]!=aim) rotate((getlc(y)==x)==(getlc(fa[y])==y)?y:x);
if (aim==0) root=x;
updata(x);
}
inline void change(int node,int x){
splay(node,null);
v[node]=x;
updata(node);
}
inline void query(int l,int r){
splay(l-1,null);
splay(r+1,root);
printf("%d\n",_max[getlc(getrc(root))]); }
inline int build(int sz){
if (sz<=0) return 0;
int t=build(sz/2),node=++cnt;
fa[ch[node][0]=t]=node;
fa[ch[node][1]=build(sz-sz/2-1)]=node;
if (node==1 || node==n+2) v[node]=-INF;
else v[node]=a[node];
updata(node);
return node;
}
int main(){
while (scanf("%d%d",&n,&m)!=EOF){
cnt=0;
memset(_max,0,sizeof(_max));
memset(fa,0,sizeof(fa));
memset(v,0,sizeof(v));
FORP(i,1,n) read(a[i+1]);
null=0;
root=build(n+2);
FORP(i,1,m){
char s[2]; scanf("%s",s); int x,y; read(x); read(y);
if (s[0]=='Q') query(x+1,y+1);
else change(x+1,y);
}
}
}
HDU 1754区间最值 & SPLAY的更多相关文章
- hdu 1754 I Hate It (splay tree伸展树)
hdu 1754 I Hate It 其实我只是来存一下我的splay模板的..请大牛们多多指教 #include<stdio.h> #include<string.h> #i ...
- HDU 1754 I Hate It (Splay 区间操作)
题目大意 维护一个序列,支持两种操作 操作一:将第x个元素的值修改为y 操作二:询问区间[x,y]内的元素的最大值 解题分析 splay的区间操作,事先加入两个编号最小和最大的点防止操作越界. 具体的 ...
- hdu 1754 I Hate It (线段树功能:单点更新和区间最值)
版权声明:本文为博主原创文章.未经博主同意不得转载.vasttian https://blog.csdn.net/u012860063/article/details/32982923 转载请注明出处 ...
- HDU 1754 I Hate It(线段树单点替换+区间最值)
I Hate It [题目链接]I Hate It [题目类型]线段树单点替换+区间最值 &题意: 本题目包含多组测试,请处理到文件结束. 在每个测试的第一行,有两个正整数 N 和 M ( 0 ...
- HDU 1754 I Hate It(线段树单点更新区间最值查询)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU】1754 I hate it ——线段树 单点更新 区间最值
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- HDU 1754 I Hate It(线段树之单点更新 区间最值查询)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- HDU 1754 I Hate It<区间最值 单点修改>
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- HDU 1754.I Hate It-完全版线段树(单点替换、区间最值)
HDU1754.I Hate It 直接模板就可以了 代码: //B #include<iostream> #include<cstdio> #include<cstri ...
随机推荐
- Sexagenary Cycle(天干地支法表示农历年份)
Sexagenary Cycle Time Limit: 2 Seconds Memory Limit: 65536 KB 题目链接:zoj 4669 The Chinese sexagen ...
- [Eclipse] eclipse中打开xml文件,使用ctrl+鼠标左键无法跳转至Java源文件【待解决】
eclipse中打开xml文件,使用ctrl+鼠标左键无法跳转至Java源文件: 1. 设置eclipse ctrl + 左键打开源文件代码,如下图,设置都正常 2. 在网上找了很多种办法,均失败,在 ...
- pthread_create传递参数
转自:http://blog.csdn.net/yeyuangen/article/details/6757525 #include <iostream> #include <pth ...
- Java Thread join() 的用法
Java Thread中, join() 方法主要是让调用改方法的thread完成run方法里面的东西后, 在执行join()方法后面的代码.示例: class ThreadTesterA imple ...
- ZEALER背后的乐视云视频
ZEALER是我非常喜欢的一个测评网站,经常访问看看手机.电动牙刷及机械键盘的测试视频,非常欣赏王自如的数据化测评理念.敬畏之心,以及不祛痘的视频. 刚好最近对网络视频应用比较感兴趣,觉得ZEALER ...
- LaTex学习笔记(一)
1. 语法 命令 普通命令 环境 数据 注释 2. 物理结构 导言 指定文档类型,引入宏包,定义命令,环境等 \documentclass[options]{class} \usepackage[op ...
- java Clone使用方法详解
java"指针" Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文会试图澄清这一概念.并且由于Java不能 通过 ...
- HDU 4496 D-City (并查集)
题意:有n个城市,m条路,首先m条路都连上,接着输出m行,第i行代表删除前i行的得到的连通块个数 题解:正难则反,我们反向考虑使用并查集添边.首先每个点都没有相连,接着倒着来边添加边计算,当两个点父节 ...
- POJ 3067 Japan(经典树状数组)
基础一维树状数组 题意:左边一排 1-n 的城市,右边一排 1-m 的城市,都从上到下依次对应.接着给你一些城市对,表示城市这两个城市相连,最后问你一共有多少个交叉,其中处于城市处的交叉不算并且每个 ...
- hdu 1003 MAX SUM 简单的dp,测试样例之间输出空行
测试样例之间输出空行,if(t>0) cout<<endl; 这样出最后一组测试样例之外,其它么每组测试样例之后都会输出一个空行. dp[i]表示以a[i]结尾的最大值,则:dp[i ...