传送门

至少BZOJ过了,其他的直接弃。

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

1.查询k在区间内的排名

2.查询区间内排名为k的值

3.修改某一位值上的数值

4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)

5.查询k在区间内的后继(后继定义为大于x,且最小的数)

最外层套一颗线段树,用来表示区间,线段树下面套个splay用来维护当前线段树节点的区间。

对于第二问可以二分,看看哪个数的排名为 k。

——代码

 #include <iostream>
#include <cstring>
#include <cstdio>
#define root 1, 1, n
#define lson now << 1, l, mid
#define rson now << 1 | 1, mid + 1, r
#define ls son[now][0]
#define rs son[now][1]
#define debug puts("**************"); const int MAXN = , INF = ; int n, m, sz;
int seq[MAXN], rt[MAXN];
int f[MAXN], son[MAXN][], cnt[MAXN], key[MAXN], size[MAXN]; inline int read()
{
int f = , x = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline int max(int x, int y)
{
return x > y ? x : y;
} inline int min(int x, int y)
{
return x < y ? x : y;
} inline void Splay_clear(int now)
{
f[now] = cnt[now] = key[now] = size[now] = ls = rs = ;
} inline void Splay_update(int now)
{
if(now)
{
size[now] = cnt[now];
if(ls) size[now] += size[ls];
if(rs) size[now] += size[rs];
}
} inline int Splay_get(int x)
{
return son[f[x]][] == x;
} inline void Splay_rotate(int x)
{
int old = f[x], oldf = f[old], wh = Splay_get(x); son[old][wh] = son[x][wh ^ ];
f[son[old][wh]] = old; son[x][wh ^ ] = old;
f[old] = x; if(oldf) son[oldf][son[oldf][] == old] = x;
f[x] = oldf; Splay_update(old);
Splay_update(x);
} inline void Splay_splay(int x)
{
for(int fa; fa = f[x]; Splay_rotate(x))
if(f[fa])
Splay_rotate(Splay_get(x) ^ Splay_get(fa) ? x : fa);
} inline void Splay_insert(int x, int k)
{
int now = rt[x], fa = ;
if(!rt[x])
{
rt[x] = ++sz;
key[sz] = k;
size[sz] = cnt[sz] = ;
return;
}
while()
{
if(k == key[now])
{
cnt[now]++;
Splay_update(now);
Splay_splay(now);
rt[x] = now;
return;
}
fa = now;
now = son[now][k > key[now]];
if(!now)
{
rt[x] = ++sz;
f[sz] = fa;
key[sz] = k;
size[sz] = cnt[sz] = ;
son[fa][k > key[fa]] = sz;
//Splay_update(fa);
Splay_splay(sz);
return;
}
}
} inline int Splay_findrank(int x, int k)
{
int now = rt[x], ans = ;
while()
{
if(!now) return ans;
if(key[now] == k) return ans + size[ls];
else if(key[now] < k)
{
ans += cnt[now] + size[ls];
now = rs;
}
else now = ls;
}
} inline int Splay_find(int x, int k)
{
int now = rt[x];
while()
{
if(key[now] > k) now = ls;
else if(key[now] < k) now = rs;
else
{
rt[x] = now;
Splay_splay(now);
return now;
}
}
} inline int Splay_pre(int x)
{
int now = son[rt[x]][];
while(rs) now = rs;
return now;
} inline int Splay_suc(int x)
{
int now = son[rt[x]][];
while(ls) now = ls;
return now;
} inline void Splay_del(int x)
{
int now = rt[x];
if(cnt[now] > )
{
cnt[now]--;
Splay_update(now);
return;
}
if(!ls && !rs)
{
rt[x] = ;
Splay_clear(now);
return;
}
if(!ls || !rs)
{
rt[x] = ls + rs;
f[rt[x]] = ;
Splay_clear(now);
return;
}
int pre = Splay_pre(x);
Splay_splay(pre);
rt[x] = pre;
son[pre][] = rs;
f[rs] = pre;
Splay_clear(now);
Splay_update(pre);
} inline int Splay_findpre(int x, int k)
{
int now = rt[x], ans = -INF;
while(now)
{
if(key[now] < k)
{
ans = max(ans, key[now]);
now = rs;
}
else now = ls;
}
return ans;
} inline int Splay_findsuc(int x, int k)
{
int now = rt[x], ans = INF;
while(now)
{
if(key[now] > k)
{
ans = min(ans, key[now]);
now = ls;
}
else now = rs;
}
return ans;
} inline void SegTree_insert(int x, int k, int now, int l, int r)
{
Splay_insert(now, k);
if(l == r) return;
int mid = (l + r) >> ;
if(x <= mid) SegTree_insert(x, k, lson);
else SegTree_insert(x, k, rson);
} inline int SegTree_askrank(int x, int y, int k, int now, int l, int r)
{
if(x <= l && r <= y) return Splay_findrank(now, k);
if(l > y || r < x) return ;
int mid = (l + r) >> ;
return SegTree_askrank(x, y, k, lson) + SegTree_askrank(x, y, k, rson);
} inline void SegTree_change(int x, int k, int now, int l, int r)
{
Splay_find(now, seq[x]);
Splay_del(now);
Splay_insert(now, k);
if(l == r) return;
int mid = (l + r) >> ;
if(x <= mid) SegTree_change(x, k, lson);
else SegTree_change(x, k, rson);
} inline int SegTree_findpre(int x, int y, int k, int now, int l, int r)
{
if(x <= l && r <= y) return Splay_findpre(now, k);
if(l > y || r < x) return -INF;
int mid = (l + r) >> ;
return max(SegTree_findpre(x, y, k, lson), SegTree_findpre(x, y, k, rson));
} inline int SegTree_findsuc(int x, int y, int k, int now, int l, int r)
{
if(x <= l && r <= y) return Splay_findsuc(now, k);
if(l > y || r < x) return INF;
int mid = (l + r) >> ;
return min(SegTree_findsuc(x, y, k, lson), SegTree_findsuc(x, y, k, rson));
} int main()
{
int i, opt, x, y, z, ans, h, t, mid, maxn = ;
n = read();
m = read();
for(i = ; i <= n; i++) seq[i] = read(), maxn = max(maxn, seq[i]), SegTree_insert(i, seq[i], root);
for(i = ; i <= m; i++)
{
opt = read();
switch(opt)
{
case :
{
x = read();
y = read();
z = read();
printf("%d\n", SegTree_askrank(x, y, z, root) + );
break;
}
case :
{
x = read();
y = read();
z = read();
h = , t = maxn;
while(h <= t)
{
mid = (h + t) >> ;
if(SegTree_askrank(x, y, mid, root) + <= z) h = mid + ;
else ans = mid, t = mid - ;
}
printf("%d\n", ans - );
break;
}
case :
{
x = read();
z = read();
SegTree_change(x, z, root);
seq[x] = z;
maxn = max(maxn, z);
break;
}
case :
{
x = read();
y = read();
z = read();
printf("%d\n", SegTree_findpre(x, y, z, root));
break;
}
case :
{
x = read();
y = read();
z = read();
printf("%d\n", SegTree_findsuc(x, y, z, root));
break;
}
}
}
return ;
}

[BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)的更多相关文章

  1. BZOJ3196 Tyvj1730 二逼平衡树 【树套树】 【线段树套treap】

    BZOJ3196 Tyvj1730 二逼平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名 ...

  2. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  3. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  4. BZOJ3196:二逼平衡树(线段树套Splay)

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在 ...

  5. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2271  Solved: 935[Submit][Stat ...

  6. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  7. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  8. BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)

    题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...

  9. [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树

    题目 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查 ...

  10. 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap

    题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义 ...

随机推荐

  1. ASP.NET MVC+Bootstrap个人博客之修复UEditor编辑时Bug(四)

    我的个人博客站在使用百度富文本编辑器UEditor修改文章时,遇到了一些问题,(不知是bug,还是我没有配置好).但总算找到了解决方法,在此记录下来. 遇到的问题: 正常来讲,进入文章修改页,只需将U ...

  2. IIS7 网站发布

    选择“网站” 添加网站

  3. iOS开发 - CoreData框架 数据持久化

    Core Data Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还 ...

  4. Thinkphp删除缓存

    控制器代码   public function delcache(){ //当找到有Runtime的文件夹时,进入if if(is_dir(RUNTIME_PATH)){ delDir(RUNTIME ...

  5. 用idea+maven编译打包spark project core错误:java.lang.RuntimeException: Unable to load a Suite class

    Discovery starting. *** RUN ABORTED *** java.lang.RuntimeException: Unable to load a Suite class tha ...

  6. Objective - c Foundation 框架详解2

    Objective - c  Foundation 框架详解2 Collection Agency Cocoa provides a number of collection classes such ...

  7. iOS---数据离线缓存

    离线缓存 为了用户的体验,不需要每次打开App都加载新数据,或者重新请求数据,因此需要把每次浏览的数据保存起来,当下次打开软件时,首先从沙盒中加载数据:或者当软件未联网时,也只能从沙盒中加载旧数据. ...

  8. vba,设置,excel,wps ,页面设置例子

    Sub yemian()'按钮1点击触发 执行下面的命令With Sheets(1).PageSetup'对像是表格1的页面设置的函数PageSetup,下面是函数的属性修改前面加. .Orienta ...

  9. leetcode_1011. Capacity To Ship Packages Within D Days_binary search二分

    https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/ 传送带每天有最大传送量V,对于n个货物[w1,w2,w3. ...

  10. 第一天 初识Python

    Python基础 一 编程语言     什么是编程语言?    上面提及的能够被计算机所识别的表达方式即编程语言,语言是沟通的介质,而编程语言是程序员与计算机沟通的介质.在编程的世界里,计算机更像是人 ...