HDU1754 I Hate It splay

题意:单等更新,区间求最值。

解题思路:splay 。

解题代码:

  1 // File Name: hdu1754.cpp
  2 // Author: darkdream
  3 // Created Time: 2015年04月03日 星期五 22时06分59秒
  4
  5 #include<vector>
  6 #include<list>
  7 #include<map>
  8 #include<set>
  9 #include<deque>
 10 #include<stack>
 11 #include<bitset>
 12 #include<algorithm>
 13 #include<functional>
 14 #include<numeric>
 15 #include<utility>
 16 #include<sstream>
 17 #include<iostream>
 18 #include<iomanip>
 19 #include<cstdio>
 20 #include<cmath>
 21 #include<cstdlib>
 22 #include<cstring>
 23 #include<ctime>
 24 #define LL long long
 25
 26 using namespace std;
 27 const int maxn = 200005;
 28 struct SplayTree{
 29     int sz[maxn];
 30     int ch[maxn][2];
 31     int pre[maxn];
 32     int root ,top1,top2;
 33     int ss[maxn],que[maxn];
 34
 35     inline void Rotate(int x,int f){
 36         int y = pre[x];
 37         push_down(y);
 38         push_down(x);
 39         ch[y][!f] = ch[x][f];
 40         pre[ch[x][f]] = y ;
 41         pre[x] = pre[y];
 42         if(pre[x]) ch[pre[y]][ch[pre[y]][1] == y] = x;
 43         ch[x][f] = y ;
 44         pre[y] = x ;
 45         push_up(y);
 46     }
 47     inline void Splay(int x, int goal){
 48          push_down(x);
 49          while(pre[x] != goal){
 50             if(pre[pre[x]] == goal){
 51                 Rotate(x, ch[pre[x]][0] == x);
 52             }else{
 53                int y = pre[x],z = pre[y];
 54                int f = (ch[z][0] == y);
 55                if(ch[y][f] == x){
 56                     Rotate(x,!f) , Rotate(x,f);
 57                }else{
 58                     Rotate(y,f) , Rotate(x,f);
 59                }
 60             }
 61          }
 62          push_up(x);
 63          if(goal ==  0) root = x;
 64     }
 65     inline void RotateTo(int k ,int goal){
 66         int x = root;
 67         push_down(x);
 68         while(sz[ch[x][0]] != k ){
 69             if(k < sz[ ch[x][0] ]){
 70                 x = ch[x][0];
 71             }else{
 72                 k -= (sz[ch[x][0]] + 1);
 73                 x = ch[x][1];
 74             }
 75             push_down(x);
 76         }
 77         Splay(x,goal);
 78     }
 79     inline void erase(int x){
 80         int father = pre[x];
 81         int head = 0 , tail = 0 ;
 82         for(que[tail ++] = x ; head < tail ;head ++){
 83             ss[top2++] = que[head];
 84             if(ch[que[head] ][0]) que[tail ++] = ch[que[head]][0];
 85             if(ch[que[head] ][1]) que[tail ++] = ch[que[head]][1];
 86         }
 87         ch[father][ch[father][1] == x] = 0 ;
 88         push_up(father);
 89     }
 90     inline void NewNode(int &x,int c){
 91          if(top2) x = ss[--top2];
 92          else x = ++top1;
 93          ch[x][0] = ch[x][1] = pre[x] = 0 ;
 94          sz[x] = 1;
 95          val[x] = mx[x] = c;
 96     }
 97     inline void push_down(int x){
 98
 99     }
100     inline void push_up(int x){
101         sz[x] = 1 + sz[ch[x][0]] + sz[ch[x][1]];
102         mx[x] = max(mx[ch[x][0]],val[x]);
103         mx[x] = max(mx[ch[x][1]],mx[x]);
104     }
105     inline void makeTree(int &x,int l ,int r,int f){
106         if(l > r) return ;
107         int m = (l + r ) >> 1;
108         NewNode(x,num[m]);
109         makeTree(ch[x][0],l,m-1,x);
110         makeTree(ch[x][1],m+1,r,x);
111         pre[x] = f;
112         push_up(x);
113     }
114     inline void init(int n){
115         ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0 ;
116         mx[0] = 0 ;
117         root = top1 = 0 ;
118         NewNode(root,-1);
119         NewNode(ch[root][1],-1);
120         pre[top1] = root;
121         sz[root] = 2;
122     //    printf("%d***\n",mx[root]);
123
124         for(int i =  1 ;i <= n;i ++) scanf("%d",&num[i]);
125         makeTree(ch[ch[root][1]][0],1,n,ch[root][1]);
126         push_up(ch[root][1]);
127         push_up(root);
128
129     //    printf("%d***\n",mx[root]);
130
131     }
132     inline void update(int l,int v){
133       RotateTo(l,0);
134       val[root] = v;
135     //  push_up(root);
136     }
137     inline void query(int l , int r){
138        RotateTo(l-1,0);
139        RotateTo(r+1,root);
140        printf("%d\n",mx[ch[ch[root][1]][0]]);
141     }
142     int num[maxn];
143     int mx[maxn];
144     int val[maxn];
145 }spt;
146 char str[10];
147 int ta,tb;
148 int n , q;
149 int main(){
150     while(scanf("%d %d",&n,&q) != EOF)
151     {
152         spt.init(n);
153         for(int i = 1;i <= q; i++)
154         {
155           scanf("%s %d %d",str,&ta,&tb);
156           if(str[0] == ‘Q‘)
157           {
158             spt.query(ta,tb);
159           }else{
160             spt.update(ta,tb);
161           }
162         }
163     }
164 return 0;
165 }

时间: 2024-10-26 17:05:35

HDU1754 I Hate It splay的相关文章

hdu1754(splay)

给n个数,有两种操作    Q a b   询问区间[a,b]的最大值,  U a b 将第a个数的值改成b splay树的中序遍历是我们所维护的序列.如果要询问区间[a,b]的最大值,那么只要将第a-1个数旋转到根结点, 将第b+1个数旋转到根的右孩子,那么根的右孩子的左子树就是所要查询的区间.我们为每一个结点维护一个最大值,表示该以该结点为根的子树的最大值,  那么答案就是 Max[next[next[root][1]][0]]; 为了防止越界, 比如要查询区间[1,n]  那么要将第0个数

HDU 1754区间最值 &amp; SPLAY

真是亲切的1754啊..第一道傻逼版的线段树做的是这个,后来学了zkw做的是这个,在后来决定打lrj线段树又打了一遍,如今再用splay和老朋友见面   从上到下依次为:加了读入优化的splay,splay,加了inline的splay,边读入边建树的lrj线段树,zkw线段树,以及线段树初体验 题意 单点修改询问区间最值. SOL: 平衡树真是优美的植物,像陀螺通过不断的优雅的旋转体现自身的平衡与美感. 对于splay的区间问题,我们利用序号来建树,当要查询一个区间时,我们把这个区间左端点的前

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

[题目分析] 模板题目. 首尾两个虚拟结点,十分方便操作. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #include

及其简短的Splay代码

#include <stdio.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <math.h> #include <iostream> #define inf 1000000000 using namespace std; #define getch() getchar() inline int F() {register int aa ,

BZOJ_1014_[JSOI2008]_火星人prefix_(Splay+LCP_Hash+二分)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1014 给出一个字符串,有修改,插入,以及询问LCP(i,j)的操作. 分析 LCP在白书上面有介绍,\(LCP(i,j)\)表示以第\(i\)位和以第\(j\)位开头的后缀的最长公共前缀. 先考虑没有插入和修改操作的问题.我们可以用基于Hash的LCP算法. 我们给每一个后缀一个Hash值.其中以第\(i\)为开头的后缀的Hash值为\(H[i]=H[i+1]x+s[i]\). 其中\(x\

BZOJ 1251 序列终结者(Splay)

题目大意 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧.[问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将 [L, R] 这个区间内的所有数加上 V. 2. 将 [

CSU 1555 Inversion Sequence 给出逆序数求排列 splay

题目链接:点击打开链接 题意: 给出逆序数的值,求原序列(一个1-N的排列) 1, 2, 0, 1, 0 表示1的逆序数是1,2的逆序数是2,3的逆序数是0··· 思路: 从最后一个数开始插,每次插到当前序列的第a[i]个数.. splay模拟 == 这个方法比较直(wu)观(nao),别的方法并没有想出来.. #include <cstdio> #include <iostream> #include <cstring> #include <queue>

【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)

http://uoj.ac/problem/31 纪念伟大的没有调出来的splay... 竟然那个find那里写错了!!!!!!!!!!!!! 以后要记住:一定要好好想过! (正解的话我就不写了,太简单了.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #

BZOJ 1507 NOI2003 Editor Splay

题目大意: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.输出光标后的一段字符 5.光标-- 6.光标++ 和1269很像的一道题,不过弱多了 几个问题需要注意: 1.插入的字符串中间居然会有回车!!没办法了,只能逐个字符进行读入,一旦读到'\n'或者'\r'就重新读入 2.题目描述中说Delete和Get操作后面一定会有足够的字符 纯属放P 连样例都没有足够的字符用来删除 所以删除时要和字符串长度取一个最小值 然后就水水地过去了~ 30%达成 今天是不是可