线段树+平衡树

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

以前的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. Elasticsearch.Net、Nest批量插入BulkAll

    demo地址:BulkAll 批量导入 实现目标:想要使用ElasticSearch的 .Net Api客户端NEST批量导入数据,并发异步高效的批量导入 NEST提供了BulkAll 不废话,上代码 ...

  2. 第二章:shiro身份验证

    身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...

  3. SSM框架使用

    现在的主流框架有SSH和SSM. SSM:SpringMVC(controller)+Spring(管理各组件)+Mybaits SSH:Struct2(controller)+Spring(管理各组 ...

  4. vuex最简单、最直白、最全的入门文档

    前言 我们经常用element-ui做后台管理系统,经常会遇到父组件给子组件传递数据,下面一个简单的例子,点击按钮,把弹框显示变量数据通过子组件的props属性传递,子组件通过$emit事件监听把数据 ...

  5. Android项目实战登录&注册

    由于项目中大部分界面都有一个后退键和一个标题栏,为避免代码冗杂以及便于利用,我们可以将后推荐和标题栏单独抽取出来定义一个标题栏布局,在 res/layout 目录下新建一个 Layout resour ...

  6. Log4j配置(xml和property两种)

    本文章为转载记录,纯粹个人备忘. 一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR 为严重错误 主要是程序的错误WARN 为一 ...

  7. 自托管websocket和webapi部署云服务器域名及远程访问

    当写完websocket和webapi服务端时,在本地测试时是没有问题的,因为是通过本地IP及端口号访问(例:127.0.0.1:8080\api\test),也就没有防火墙等安全限制,但当部署到云服 ...

  8. vue和angular的区别:

    相同: 1.数据绑定:vue和angular绑定都可以用{{}} 2.都支持内置指令和自定义指令 3.都支持内置过滤器和自定义过滤器. 区别: 1.学习成本和API 设计:vue相比于angular来 ...

  9. IKAnalyzer结合Lucene实现中文分词

    1.基本介绍 随着分词在信息检索领域应用的越来越广泛,分词这门技术对大家并不陌生.对于英文分词处理相对简单,经过拆分单词.排斥停止词.提取词干的过程基本就能实现英文分词,单对于中文分词而言,由于语义的 ...

  10. SpringBoot中集成Swagger2

    1.依赖jar <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-s ...