hdu1754I Hate It(splay)

链接

线段树的水题,拿来学习一下splay.

本题涉及到求最大值以及单点更新,折腾了许久,差不多把splay搞明白了。

按位置建树,按位置是一颗排序二叉树,对于区间的操作非常方便,每次操作都将需要的结点转自根的右孩子的左孩子,因为加了2个结点,一个最小的,一个最大的,据说是为了防止越界。

这题只有单点,所以每次将所求结点旋自根节点即可。

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 using namespace std;
 11 #define N 200010
 12 #define LL __int64
 13 #define INF 0xfffffff
 14 #define key_value ch[ch[root][1]][0]
 15 const double eps = 1e-8;
 16 const double pi = acos(-1.0);
 17 const double inf = ~0u>>2;
 18 int pre[N],s[N],size[N];
 19 int ch[N][2],a[N],val[N];
 20 int root,n,tot;
 21 void newnode(int &x,int k,int fa)
 22 {
 23     x = ++tot;
 24     ch[x][0]=ch[x][1] = 0;
 25     pre[x] = fa;
 26     size[x] = 1;
 27     s[x] = k;
 28     val[x] = k;
 29 }
 30 void pushup(int w)
 31 {
 32     size[w] = size[ch[w][0]]+size[ch[w][1]]+1;
 33     s[w] = max(max(s[ch[w][0]],s[ch[w][1]]),val[w]);
 34    // cout<<s[w]<<" "<<w<<"// "<<" "<<ch[w][1]<<" "<<s[w]<<endl;
 35 }
 36 void rotate(int r,int kind)
 37 {
 38     int y = pre[r];
 39     ch[y][!kind] = ch[r][kind];
 40     pre[ch[r][kind]] = y;
 41     if(pre[y])
 42     {
 43         ch[pre[y]][ch[pre[y]][1]==y] = r;
 44     }
 45     pre[r] = pre[y];
 46     ch[r][kind] = y;
 47     pre[y] = r;
 48     pushup(y);
 49     //pushup(r);
 50 }
 51 void splay(int r,int goal)
 52 {
 53     while(pre[r]!=goal)
 54     {
 55        if(pre[pre[r]]==goal)
 56         {
 57              rotate(r,ch[pre[r]][0]==r);
 58         }
 59         else
 60         {
 61             int y = pre[r];
 62             int kind = (ch[pre[y]][0]==y);
 63             if(ch[y][kind]==r)
 64             {
 65                 rotate(r,!kind);
 66                 rotate(r,kind);
 67             }
 68             else
 69             {
 70                 rotate(y,kind);
 71                 rotate(r,kind);
 72             }
 73         }
 74     }
 75     pushup(r);
 76     if(goal==0) root = r;
 77 }
 78 int get_k(int k)
 79 {
 80     int r = root;
 81     while(size[ch[r][0]]!=k)
 82     {
 83         if(size[ch[r][0]]>k)
 84         r = ch[r][0];
 85         else
 86         {
 87             k-=(size[ch[r][0]]+1);
 88             r = ch[r][1];
 89         }
 90     }
 91     return r;
 92 }
 93 int query(int l,int r)
 94 {
 95     splay(get_k(l-1),0);
 96     splay(get_k(r+1),root);
 97     return s[key_value];
 98 }
 99 /*void update(int l,int r,int k)
100 {
101     splay(get_k(l-1),0);
102     splay(get_k(r+1),root);
103     val[key_value] = k;
104     s[key_value] = k;
105     pushup(ch[root][1]);
106     pushup(root);
107 }*/
108 void update(int l,int r,int k)
109 {
110     int kk = get_k(l);
111     val[kk] = k;
112     splay(kk,0);
113 }
114 void build(int &w,int l,int r,int fa)
115 {
116     if(l>r) return ;
117     int m = (l+r)>>1;
118     newnode(w,a[m],fa);
119     build(ch[w][0],l,m-1,w);
120     build(ch[w][1],m+1,r,w);
121     pushup(w);
122 }
123 void init()
124 {
125     int i;
126     for(i = 0 ;i < n ;i++)
127     scanf("%d",&a[i]);
128     ch[0][0] = ch[0][1] = pre[0] = size[0] = s[0] = 0;
129     root = tot =0;
130     newnode(root,-1,0);
131     newnode(ch[root][1],-1,root);
132     size[root] = 2;
133     build(key_value,0,n-1,ch[root][1]);
134     pushup(ch[root][1]);
135     pushup(root);
136 }
137 int main()
138 {
139     int q,x,y,i;
140     char sq[10];
141     while(scanf("%d%d",&n,&q)!=EOF)
142     {
143         init();
144         while(q--)
145         {
146             scanf("%s%d%d",sq,&x,&y);
147             if(sq[0]==‘U‘)
148             {
149                 update(x,x,y);
150                 /*for(i = 0; i <= n+2; i++)
151                 cout<<ch[i][0]<<" "<<ch[i][1]<<" "<<i<<endl;
152                 puts("");*/
153             }
154             else
155             {
156                 printf("%d\n",query(x,y));
157                 /*for(i = 0; i <= n+2; i++)
158                 cout<<ch[i][0]<<" "<<ch[i][1]<<" "<<i<<endl;
159                 puts("");*/
160             }
161         }
162     }
163     return 0;
164 }

hdu1754I Hate It(splay)

时间: 2024-12-09 06:47:55

hdu1754I Hate It(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%达成 今天是不是可

【Splay】【启发式合并】hdu6133 Army Formations

题意:给你一颗树,每个结点的儿子数不超过2.每个结点有一个权值,一个结点的代价被定义为将其子树中所有结点的权值放入数组排序后,每个权值乘以其下标的和.让你计算所有结点的代价. 二叉树的条件没有用到. 每个结点开一个Splay,从叶子往上启发式合并上去,可以先bfs一遍确定合并顺序.每一次将Splay大小较小的结点的权值全提取出来塞到较大的里面. 由于权值可能重复出现,所以每个结点记个cnt. 答案统计的时候,就将那个刚塞进去的旋到根,然后答案加上左子树的权值和,再加上(右子树的权值的个数+该结点

数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) #include <cstdio> #define Max 100005 #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (int &now) { now = 0; register char word = getchar (); bool temp = false; while (wor