线段树+平衡树

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

以前的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. 用jQuery实现切换动态图片

    1.实现动态图片的切换只需要改变目标图片的路径

  2. 【开源分享】2018CRM C# 源码(基于小黄豆CRMv2.0.925.3版本功能更新)

    分享出来的初衷,我分享一下最近我在小黄豆CRM2.0版本(小黄豆CRM+v2.0.925.3)上加的功能,如果有类似需求的,可以把功能代码发你,节约你的开发时间.(这是在小黄豆开源免费CRM①群231 ...

  3. C# 读取PDF多级书签

    在PDF中,书签作为一种导航的有效工具,能帮助我们快速地定位到文档中的指定段落.同时,书签也能让人对文档结构一目了然,在某种程度上也可作为目录使用.对于C#操作PDF中的书签,在上一篇文章中介绍了具体 ...

  4. Java开发笔记(八十六)通过缓冲区读写文件

    前面介绍了利用文件写入器和文件读取器来读写文件,因为FileWriter与FileReader读写的数据以字符为单位,所以这种读写文件的方式被称作“字符流I/O”,其中字母I代表输入Input,字母O ...

  5. 在表单提交之前做校验-利用jQuery的submit方法

    点击表单中的提交按钮,默认就会提交表单,如果要在表单提交之前做一些校验,那么就可以用jQuery的submit方法. 也就是jQuery的submit的方法执行顺序,在表单的提交之前.用法如下: $( ...

  6. Spring boot项目maven的profile多环境配置不自动替换变量的问题解决

    Spring boot项目maven的profile多环境配置不自动替换变量的问题解决   在网上找了好久,配置都很简单,可是我的程序就是不能自动替换变量,最终单独测试,发现原来是引用spring b ...

  7. java工作流引擎Jflow父子流程demo

    关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow  .net开源工作流 定义 一个流程A的一个节点,因工作的需要调起另外的流程B,A就叫父流程,B就叫子流程.如果流 ...

  8. 【设计模式】简单工厂模式 Simple Factory Pattern

    简单工厂模式Simple Factory Pattern[Simple Factory Pattern]是设计模式里最简单的一个模式,又叫静态工厂模式[Static Factory Pattern], ...

  9. 链表倒数第k个节点

    1.一种较笨的办法是先将链表元素入栈,然后出栈找到倒数第k个节点值,再拿着值遍历链表去找到对于节点. 时间复杂度:O(n) (3n 遍历-出栈-遍历) 空间复杂度:O(n) (一个栈) 2.快慢指针, ...

  10. 一:SqlServer中的 CEILING函数和 FLOOR函数以及ROUND()

    例如 1.ROUND() 格式为ROUND(y1,y2,y3) y1:要被四舍五入的数字y2:保留的小数位数 y3:为0,可以不写,y1进行四舍五入,不为0则y1不进入四舍五入,如果y1有值就直接根据 ...