线段树+平衡树

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

以前的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. MVC,EF 小小封装

    1.项目中经常要用到 EF,有时候大多数的增删改查都是重复性的东西,本次封装就是为了快速开发,期间没有考虑到架构上的各种思想,就感觉到欠缺点什么东西所以这次将这些拉出来,有存在问题的话还请各位多多指导 ...

  2. ITSA(IT Strategy and Architecture)方法介绍

    Architecture Capability – At a Glance Architectural coherence part1 Architectural coherence part2 SA ...

  3. Editplus的扩展程序的删除

    好久没用Editplus,然后准备删除,结果发现有进程正在运行,删除不掉 ,于是,用软件管家删除 用软件管家删除结束之后,有残留文件,就是Editplus的扩展程序        1.于是找到Edit ...

  4. 洛谷P2664 树上游戏(点分治)

    题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...

  5. 【设计模式】建造者模式 Builder Pattern

    前面学习了简单工厂模式,工厂方法模式以及抽象工厂模式,这些都是创建类的对象所使用的一些常用的方法和套路, 那么如果我们创建一个很复杂的对象可上面的三种方法都不太适合,那么“专业的事交给专业人去做”,2 ...

  6. 四、Snapman多人协作电子表格之——Exprtk脚本

    Snapman多人协作电子表格是一个即时工作系统. Snapman中嵌入了Exprtk脚本进行公式数据运算.Exprtk是一种高性能的脚本,经测试它的数据运算性能只比C#和java底20%. 一.Ex ...

  7. 微信小程序推广技巧、营销方案

    小程序已经成功上线了!那么,小程序线下如何推广?线下门店如何玩转小程序呢? 1.附近的小程序,让商家曝光率更高 小 程序自带“附近的小程序”功能,利用LBS定位功能提高商家专属微信小程序的曝光度,用户 ...

  8. Python第十五天 datetime模块 time模块 thread模块 threading模块 Queue队列模块 multiprocessing模块 paramiko模块 fabric模块

    Python第十五天  datetime模块 time模块   thread模块  threading模块  Queue队列模块  multiprocessing模块  paramiko模块  fab ...

  9. SQLServer创建用户自定义数据库用户

    创建用户自定义数据库用户注意事项 如果已忽略 FOR LOGIN,则新的数据库用户将被映射到同名的SQL Server登录名. 默认架构将是服务器为此数据库用户解析对象名时将搜索的第一个架构. 除非另 ...

  10. ASP.NET实现二维码

    using System;using System.Collections.Generic;using System.Drawing;using System.Linq;using System.Te ...