线段树+平衡树

我!又!被!卡!常!了!

以前的splay偷懒的删除找前驱后继的办法被卡了QAQ

放一个在洛谷开O2才能过的代码。。我太菜了。。

#include <bits/stdc++.h>
#define INF 2147483647
#define rint register int
#define full(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
int X = 0, w = 0; char ch = 0;
while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
return w ? -X : X;
}
static short c[20], top;
inline void print(int x){
if(!x){ putchar(48); putchar('\n'); return;}
if(x < 0) putchar('-'),x *= -1;
for(top = 0; x ; c[++top] = x % 10, x /= 10);
for(; top; putchar(c[top--]^48));
putchar('\n');
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
A ans = 1;
for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
return ans;
} const int N = 3000005;
int n, m, tot, tmp, root[N], val[N], size[N], fa[N], ch[N][2], cnt[N], a[N]; inline int init(rint v, rint f){
++tot;
val[tot] = v, fa[tot] = f, size[tot] = cnt[tot] = 1;
ch[tot][0] = ch[tot][1] = 0;
return tot;
} inline void push_up(rint x){
size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x];
} inline void rotate(rint x){
int y = fa[x], z = fa[y], p = (ch[y][1] == x) ^ 1;
ch[y][p^1] = ch[x][p], fa[ch[x][p]] = y;
ch[z][ch[z][1] == y] = x, fa[x] = z;
ch[x][p] = y, fa[y] = x;
push_up(y), push_up(x);
} inline void splay(rint i, rint x, rint goal){
if(x == goal) return;
while(fa[x] != goal){
int y = fa[x], z = fa[y];
if(z != goal){
(ch[y][0] == x) ^ (ch[z][0] == y) ? rotate(x) : rotate(y);
}
rotate(x);
}
push_up(x);
if(goal == 0) root[i] = x;
} inline void insert(rint i, rint x){
if(!root[i]){
root[i] = init(x, 0);
return;
}
rint cur = root[i];
while(ch[cur][x > val[cur]]){
if(x == val[cur]) break;
cur = ch[cur][x > val[cur]];
}
if(x == val[cur]) cnt[cur] ++, splay(i, cur, 0);
else ch[cur][x > val[cur]] = init(x, cur), splay(i, ch[cur][x > val[cur]], 0);
} inline void find(rint i, rint x){
if(!root[i]) return;
rint cur = root[i];
while(x != val[cur] && ch[cur][x > val[cur]])
cur = ch[cur][x > val[cur]];
splay(i, cur, 0);
} /*inline int precursor(rint i, rint x){
find(i, x);
if(val[root[i]] < x) return root[i];
rint cur = ch[root[i]][0];
while(ch[cur][1]) cur = ch[cur][1];
return cur;
} inline int successor(rint i, rint x){
find(i, x);
if(val[root[i]] > x) return root[i];
rint cur = ch[root[i]][1];
while(ch[cur][0]) cur = ch[cur][0];
return cur;
}*/ inline int precursor(int i, int v){
int x = root[i], ans = -INF;
while (x){
if (val[x] < v){
if (ans < val[x]) ans = val[x];
x = ch[x][1];
}
else x = ch[x][0];
}
return ans;
} inline int successor(int i, int v){
int x = root[i], ans = INF;
while (x){
if (val[x] > v){
if (ans > val[x]) ans = val[x];
x = ch[x][0];
}
else x = ch[x][1];
} return ans;
} inline void remove(rint i, rint x){
rint pre = precursor(i, x), suc = successor(i, x);
splay(i, pre, 0), splay(i, suc, root[i]);
rint key = ch[suc][0];
if(cnt[key] > 1) cnt[key] --, splay(i, key, 0);
else ch[suc][0] = 0;
push_up(suc);
} inline void clear(int x){
fa[x] = ch[x][0] = ch[x][1] = size[x] = cnt[x] = val[x] = 0;
} inline void del(rint i, rint x){
find(i, x);
int cur = root[i];
if(cnt[cur] > 1){
cnt[cur] --;
return;
}
if(!ch[cur][0]){
int y = ch[cur][1];
root[i] = y, fa[y] = 0;
return;
}
if(!ch[cur][1]){
int y = ch[cur][0];
root[i] = y, fa[y] = 0;
return;
}
int p = ch[cur][0];
while(ch[p][1]) p = ch[p][1];
int oldrt = root[i];
splay(i, p, 0);
ch[root[i]][1] = ch[oldrt][1];
fa[ch[oldrt][1]] = root[i];
clear(oldrt);
push_up(root[i]);
return;
} void buildTree(rint rt, rint l, rint r){
insert(rt, INF), insert(rt, -INF);
if(l == r) return;
rint mid = (l + r) >> 1;
buildTree(rt << 1, l, mid);
buildTree(rt << 1 | 1, mid + 1, r);
push_up(rt);
} void segInsert(rint rt, rint l, rint r, rint k, rint x){
insert(rt, x);
if(l == r) return;
rint mid = (l + r) >> 1;
if(k <= mid) segInsert(rt << 1, l, mid, k, x);
else segInsert(rt << 1 | 1, mid + 1, r, k, x);
} int segRank(rint rt, rint l, rint r, rint x, rint ql, rint qr){
if(l == ql && r == qr){
find(rt, x);
if(val[root[rt]] >= x) return size[ch[root[rt]][0]] - 1;
return size[ch[root[rt]][0]] + cnt[root[rt]] - 1;
}
rint mid = (l + r) >> 1;
if(qr <= mid) return segRank(rt << 1, l, mid, x, ql, qr);
else if(ql > mid) return segRank(rt << 1 | 1, mid + 1, r, x, ql, qr);
return segRank(rt << 1, l, mid, x, ql, mid) + segRank(rt << 1 | 1, mid + 1, r, x, mid + 1, qr);
} void segModify(rint rt, rint l, rint r, rint pos, rint k){
insert(rt, k), del(rt, a[pos]);
if(l == r) return;
rint mid = (l +r) >> 1;
if(pos <= mid) segModify(rt << 1, l, mid, pos, k);
else segModify(rt << 1 | 1, mid + 1, r, pos, k);
} int segPrecursor(rint rt, rint l, rint r, rint x, rint ql, rint qr){
if(l == ql && r == qr){
return precursor(rt, x);
}
rint mid = (l + r) >> 1;
if(qr <= mid) return segPrecursor(rt << 1, l, mid, x, ql, qr);
else if(ql > mid) return segPrecursor(rt << 1 | 1, mid + 1, r, x, ql, qr);
return max(segPrecursor(rt << 1, l, mid, x, ql, mid), segPrecursor(rt << 1 | 1, mid + 1, r, x, mid + 1, qr));
} int segSuccessor(rint rt, rint l, rint r, rint x, rint ql, rint qr){
if(l == ql && r == qr){
return successor(rt, x);
}
rint mid = (l + r) >> 1;
if(qr <= mid) return segSuccessor(rt << 1, l, mid, x, ql, qr);
else if(ql > mid) return segSuccessor(rt << 1 | 1, mid + 1, r, x, ql, qr);
return min(segSuccessor(rt << 1, l, mid, x, ql, mid), segSuccessor(rt << 1 | 1, mid + 1, r, x, mid + 1, qr));
} inline int select(rint l, rint r, rint k){
rint ll = 0, rr = tmp;
while(ll < rr){
rint mid = (ll + rr + 1) >> 1;
if(segRank(1, 1, n, mid, l, r) + 1 > k) rr = mid - 1;
else ll = mid;
}
return ll;
} int main(){ //freopen("data.txt","r",stdin); //clock_t startTime = clock(); n = read(), m = read();
tmp = -INF;
buildTree(1, 1, n);
for(rint i = 1; i <= n; i ++) a[i] = read(), tmp = max(tmp, a[i]), segInsert(1, 1, n, i, a[i]);
while(m --){
rint opt = read();
if(opt == 1){
rint l = read(), r = read(), k = read();
print(segRank(1, 1, n, k, l, r) + 1);
//printf("%d\n", segRank(1, 1, n, k, l, r) + 1);
}
else if(opt == 2){
rint l = read(), r = read(), k = read();
print(select(l, r, k));
//printf("%d\n", select(l, r, k));
}
else if(opt == 3){
rint pos = read(), k = read();
segModify(1, 1, n, pos, k);
a[pos] = k;
}
else if(opt == 4){
rint l = read(), r = read(), k = read();
print(segPrecursor(1, 1, n, k, l, r));
//printf("%d\n", segPrecursor(1, 1, n, k, l, r));
}
else if(opt == 5){
rint l = read(), r = read(), k = read();
print(segSuccessor(1, 1, n, k, l, r));
//printf("%d\n", segSuccessor(1, 1, n, k, l, r));
}
} //clock_t endTime = clock(); //cout << "time: " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl; return 0;
}

洛谷P3380 二逼平衡树的更多相关文章

  1. 洛谷P3380 【模板】二逼平衡树(树套树)(线段树+树状数组)

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

  2. 洛谷 P3380 【模板】二逼平衡树(树套树)-线段树套splay

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

  3. 洛谷 P3380 bzoj3196 Tyvj1730 【模板】二逼平衡树(树套树)

    [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在 ...

  4. P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)

    P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...

  5. 【题解】二逼平衡树 [P3380] [BZOJ3196] [Tyvj1730]

    [题解]二逼平衡树 [P3380] [BZOJ3196] [Tyvj1730] 传送门:[模板]二逼平衡树(树套树)\([P3380]\) \([BZOJ3196]\) \([TYVJ1730]\) ...

  6. bzoj 3196: Tyvj 1730 二逼平衡树

    #include<cstdio> #include<ctime> #include<cstdlib> #include<iostream> #defin ...

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

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

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

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

  9. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

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

随机推荐

  1. 推荐三个 VSCode 摸鱼插件

    周三是一周中最难以度过的一天,离上个周末过去了两天,离下个周末也还有两天.为了让各位更好地搬(mo)砖(yu),今天给大家推荐三款效(mo)率(yu)工(shen)具(qi)! 一.听歌插件 1 功能 ...

  2. .net core EFcore model生成数据

    创建数据库 (扫盲贴还劳烦大神们勿喷,谢谢) 打开数据库 输入如下代码 创建数据库 CREATE DATABASE [Blogging]; GO USE [Blogging]; GO CREATE T ...

  3. 驰骋开源的asp.net工作流程引擎java工作流 2015 正文 驰骋工作流引擎ccflow6的功能列表

    关键词: 驰骋工作流引擎   ccflow的功能列表   工作流功能列表  表单引擎功能列表 我们工作流引擎ccflow6重构之后对功能做了一些调整,要想快速了解ccbpm的功能,可以以下面列表为准 ...

  4. [C#学习笔记3]关于Main(string[ ] args)中args命令行参数

    Main(string[] args)方法是C#程序的入口,程序从这里开始执行,在这里结束.C#代码逻辑要包含在一个类型(Type)中,游离的.全局的变量或函数是不存在的,这里的类型包括类(class ...

  5. 【设计模式】原型模式 Pototype Pattern

    前面讲了创建一个对象实例的方法单例模式Singleton Pattern, 创造多个产品的工厂模式(简单工厂模式 Simple Factory Pattern, 工厂方法模式 FactoryMothe ...

  6. Windows -- 从注册表删除IE浏览器加载项

    Windows -- 从注册表删除IE浏览器加载项 1.  一部分加载项从注册表以下位置直接删除 2.  一部分扩展项从注册表以下位置直接删除

  7. MySQL慢查询&执行计划

    参考文章: https://blog.csdn.net/tiantianw/article/details/53334566 http://www.cnblogs.com/luyucheng/p/62 ...

  8. Elastic Stack-Elasticsearch使用介绍(六)

    一.前言     很久没有更新博客,实在对不住大家.从10月份假期以后我就开始优化程序,来应对双11,这段时间确实很忙,不好意思.好在优化效果还不错,我负责的模块在双11期间没有任何大问题,整体效果还 ...

  9. JAVA之字符串

    求字符串长度: 使用.length()方法: 注意:字符串是使用字符串类里的方法,而数组是用数组类里的变量,因此数组是.length. String str="123456789" ...

  10. 美化ubuntu18.04,并安装搜狗输入法

    目录 美化Ubuntu 下载主题和图标文件 下载GNOME3 美化过程 安装输入法 下载并安装搜狗输入法 安装fcitx框架 安装过程 美化Ubuntu 下载主题和图标文件 下载地址:https:// ...