BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树
之前写线段树套splay数组版。。写了6.2k。。然后弃疗了。现在发现还是很水的。。嘎嘎。。
zju过不了,超时。
upd:才发现zju是多组数据。。TLE一版才发现。然后改了,MLE。。。手写内存池。。尼玛终于过了。。附zju2112代码于后。

bzoj倒是过了,1A的感觉还是很爽的。。可是时间不好看。。这就是所谓\(O(nlog^3n)\)的复杂度的可怜之处么?
写挂的地方:
- insert一定要是传地址指针进去。
- delete时先把地址指针delete掉,最后把是地址指针指向左儿子or右儿子or NULL。
- 节点初始化时一定要把左右儿子指针指向NULL。
- 注意脑残,b打错变量名的问题。
做法:线段树约束区间,平衡树支持修改和查询,没了。
修改:每次在包含点的线段树节点所包含的平衡树中删除要改的节点值,在插入新的值,\(O(log^2n)\)。
查询:由于无法直接查询,所以二分答案,求得答案在区间內的排名,等于各区间小于该值的节点数量,select直接搞,总共\(O(log^3n)\),具体可以先插入一个值节点,在求值节点的rank,最后删掉即可。
我是用线段树套treap。
然后树状数组套平衡树也可以过,常数小很多。。。
达成成就:AC树套树。
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cstring>
typedef long long LL;
const int maxn = + ;
int n, m, sum, a[maxn], INF = 0x3f3f3f3f;
struct treap_node {
treap_node *ch[];
int key, fix, cnt, size;
treap_node() {
ch[] = ch[] = NULL;
}
treap_node(int _key) {
ch[] = ch[] = NULL;
key = _key;
size = cnt = ;
fix = rand();
}
} *T[maxn << ];
inline void maintain(treap_node *t) {
t->size = t->cnt;
if(t->ch[]) t->size += t->ch[]->size;
if(t->ch[]) t->size += t->ch[]->size;
}
void rot(treap_node *&t, int d) {
treap_node *p = t->ch[d ^ ];
t->ch[d ^ ] = p->ch[d], p->ch[d] = t;
maintain(t), maintain(p);
t = p;
}
void insert(treap_node *&t, int val) {
if(t == NULL) {
t = new treap_node(val);
} else {
if(val < t->key) {
insert(t->ch[], val);
if(t->ch[]->fix < t->fix) rot(t, );
} else if(t->key < val) {
insert(t->ch[], val);
if(t->ch[]->fix < t->fix) rot(t, );
} else
++t->cnt;
}
maintain(t);
}
void del(treap_node *&t, int val) {
if(t->key == val) {
if(t->cnt == ) {
if(!t->ch[] || !t->ch[]) {
treap_node *p = t;
if(!p->ch[]) p = t->ch[];
else p = t->ch[];
delete t;
t = p;
} else {
int d = t->ch[]->fix < t->ch[]->fix;
rot(t, d);
del(t->ch[d], val);
}
} else --t->cnt;
} else del(t->ch[t->key < val], val);
if(t) maintain(t);
}
int select(treap_node *t, int val) {
if(t == NULL) return ;
if(val < t->key) return select(t->ch[], val);
int p = (t->ch[]) ? t->ch[]->size + t->cnt : t->cnt;
if(t->key < val) p += select(t->ch[], val);
return p;
}
bool ok;
void query(int l, int r, int rt, int ql, int qr, int val) {
if(ql <= l && r <= qr) {
sum += select(T[rt], val);
return ;
} else {
int mid = (l + r) >> ;
if(ql <= mid) query(l, mid, rt << , ql, qr, val);
if(mid < qr) query(mid + , r, rt << | , ql, qr, val);
}
}
void seg_del(int l, int r, int rt, int pos, int val) {
del(T[rt], val);
if(l == r) return ;
int mid = (l + r) >> ;
if(pos <= mid) seg_del(l, mid, rt << , pos, val);
else if(mid < pos) seg_del(mid + , r, rt << | , pos, val);
}
void seg_insert(int l, int r, int rt, int pos, int val) {
insert(T[rt], val);
if(l == r) return ;
int mid = (l + r) >> ;
if(pos <= mid) seg_insert(l, mid, rt << , pos, val);
else if(mid < pos) seg_insert(mid + , r, rt << | , pos, val);
} char gchar() {
char ret = getchar();
for(; ret == '\n' || ret == '\r' || ret == ' '; ret = getchar());
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin), freopen("data.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
srand(n * m + );
for(int i = ; i <= n; ++i) {
scanf("%d", &a[i]);
seg_insert(, n, , i, a[i]);
}
ok = false;
for(int i = , p, b, c, d; i <= m; ++i) {
d = gchar();
if(d == 'C') {
scanf("%d%d", &p, &b);
seg_del(, n, , p, a[p]);
a[p] = b;
seg_insert(, n, , p, a[p]);
} else {
scanf("%d%d%d", &b, &c, &p);
LL l = , r = INF;
while(l < r) {
LL mid = (l + r) >> ;
sum = ;
query(, n, , b, c, mid);
if(sum < p) {
l = mid + ;
} else {
r = mid;
}
}
printf("%lld\n", l);
}
}
return ;
}
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cstring>
typedef long long LL;
const int maxn = + ;
int n, m, sum, a[maxn], INF = 0x3f3f3f3f;
struct treap_node {
treap_node *ch[];
int key, fix, cnt, size;
treap_node() {
ch[] = ch[] = NULL;
}
treap_node(int _key) {
ch[] = ch[] = NULL;
key = _key;
size = cnt = ;
fix = rand();
}
} *T[maxn << ];
treap_node null_thing;
struct storage {
treap_node free_node[maxn * ];
int top, rec;
void init() {
rec = maxn * ;
for(int i = ; i < rec; ++i) free_node[top++] = i;
}
treap_node _new(int val) {
return free_node[--top] = treap_node(val);
}
void back_data() {
for(int i = top; i < rec; ++i) free_node[top++] = i;
}
}S; inline void maintain(treap_node *t) {
t->size = t->cnt;
if(t->ch[]) t->size += t->ch[]->size;
if(t->ch[]) t->size += t->ch[]->size;
}
void rot(treap_node *&t, int d) {
treap_node *p = t->ch[d ^ ];
t->ch[d ^ ] = p->ch[d], p->ch[d] = t;
maintain(t), maintain(p);
t = p;
}
void insert(treap_node *&t, int val) {
if(t == NULL) {
S._new(val);
t = &S.free_node[S.top];
} else {
if(val < t->key) {
insert(t->ch[], val);
if(t->ch[]->fix < t->fix) rot(t, );
} else if(t->key < val) {
insert(t->ch[], val);
if(t->ch[]->fix < t->fix) rot(t, );
} else
++t->cnt;
}
maintain(t);
}
void del(treap_node *&t, int val) {
if(t->key == val) {
if(t->cnt == ) {
if(!t->ch[] || !t->ch[]) {
treap_node *p = t;
if(!p->ch[]) p = t->ch[];
else p = t->ch[];
t = p;
} else {
int d = t->ch[]->fix < t->ch[]->fix;
rot(t, d);
del(t->ch[d], val);
}
} else --t->cnt;
} else del(t->ch[t->key < val], val);
if(t) maintain(t);
}
int select(treap_node *t, int val) {
if(t == NULL) return ;
if(val < t->key) return select(t->ch[], val);
int p = (t->ch[]) ? t->ch[]->size + t->cnt : t->cnt;
if(t->key < val) p += select(t->ch[], val);
return p;
}
bool ok;
void query(int l, int r, int rt, int ql, int qr, int val) {
if(ql <= l && r <= qr) {
sum += select(T[rt], val);
return ;
} else {
int mid = (l + r) >> ;
if(ql <= mid) query(l, mid, rt << , ql, qr, val);
if(mid < qr) query(mid + , r, rt << | , ql, qr, val);
}
}
void seg_del(int l, int r, int rt, int pos, int val) {
del(T[rt], val);
if(l == r) return ;
int mid = (l + r) >> ;
if(pos <= mid) seg_del(l, mid, rt << , pos, val);
else if(mid < pos) seg_del(mid + , r, rt << | , pos, val);
}
void seg_insert(int l, int r, int rt, int pos, int val) {
insert(T[rt], val);
if(l == r) return ;
int mid = (l + r) >> ;
if(pos <= mid) seg_insert(l, mid, rt << , pos, val);
else if(mid < pos) seg_insert(mid + , r, rt << | , pos, val);
} char gchar() {
char ret = getchar();
for(; ret == '\n' || ret == '\r' || ret == ' '; ret = getchar());
return ret;
}
void del_tree(int l, int r, int rt) {
T[rt] = NULL;
if(l == r) return ;
int mid = (l + r) >> ;
del_tree(l, mid, rt << );
del_tree(mid + , r, rt << | );
}
int main() { int test_num;
scanf("%d", &test_num);
S.init();
while(test_num--) {
S.back_data();
scanf("%d%d", &n, &m);
del_tree(, n, );
srand(n * m + );
for(int i = ; i <= n; ++i) {
scanf("%d", &a[i]);
seg_insert(, n, , i, a[i]);
}
ok = false;
for(int i = , p, b, c, d; i <= m; ++i) {
d = gchar();
if(d == 'C') {
scanf("%d%d", &p, &b);
seg_del(, n, , p, a[p]);
a[p] = b;
seg_insert(, n, , p, a[p]);
} else {
scanf("%d%d%d", &b, &c, &p);
LL l = , r = INF;
while(l < r) {
LL mid = (l + r) >> ;
sum = ;
query(, n, , b, c, mid);
if(sum < p) {
l = mid + ;
} else {
r = mid;
}
}
printf("%lld\n", l);
}
}
}
return ;
}
zju 2112
BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树的更多相关文章
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- bzoj 1901: Zju2112 Dynamic Rankings(树套树)
1901: Zju2112 Dynamic Rankings 经典的带改动求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,并且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过 ...
- BZOJ 1901 Zju2112 Dynamic Rankings
树阵主席设置树.维护间隔动态K大. .. ZOJ到空间太小,太大,仅仅能到BZOJ上交 1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memor ...
- BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 7143 Solved: 2968[Su ...
- Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6471 Solved: 2697[Su ...
- Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6321 Solved: 2628[Su ...
- bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1] ...
- BZOJ 1901: Zju2112 Dynamic Rankings( 树状数组套主席树 )
裸的带修改主席树.. 之前用BIT套Splay( http://www.cnblogs.com/JSZX11556/p/4625552.html )A过..但是还是线段树好写...而且快(常数比平衡树 ...
- BZOJ 1901: Zju2112 Dynamic Rankings( BIT 套 BST )
BIT 套 splay 其实也是不难...每个 BIT 的结点保存一颗 splay , 询问就二分答案然后判断rank... ------------------------------------- ...
随机推荐
- 调整KVM虚拟机硬盘大小
KVM虚拟机的硬盘映像默认存放在“/var/lib/libvirt/images/”中,先查看你的硬盘映像格式是不是RAW格式: qemu-img info /var/lib/libvirt/imag ...
- Ubuntu 14.04 64bit下Caffe + Cuda6.5/Cuda7.0 安装配置教程
http://www.embeddedlinux.org.cn/emb-linux/entry-level/201612/21-6005.html 随着深度学习快速发展的浪潮,许多有兴趣的工作者都转入 ...
- The Shortest Path in Nya Graph HDU - 4725
Problem Description This is a very easy problem, your task is just calculate el camino mas corto en ...
- javascript实现正整数分数约分
//m,n为正整数的分子和分母 function reductionTo(m, n) { var arr = []; if (!isInteger(m) || !isInteger(n)) { con ...
- 给定一个数字n,不用for循环实现输出数组 [1,2,3,4,...,n]
一.for循环方式实现输出[1, 2, 3, ..., n] var n = 5; function test(n){ var arr=[]; for( var i = 1; i <= n; i ...
- 浅谈移动端三大viewport
我们通常在写移动端页面时,往往都会在html页面中加入这样一段话 <meta name="viewport" content="width=device-width ...
- Codeforces 617E XOR and Favorite Number莫队
http://codeforces.com/contest/617/problem/E 题意:给出q个查询,每次询问区间内连续异或值为k的有几种情况. 思路:没有区间修改,而且扩展端点,减小端点在前缀 ...
- [洛谷P2023] [AHOI2009]维护序列
洛谷题目链接:[AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列 ...
- 嵌入式Nosql数据库——LiteDB
LiteDB是一个开源的 .NET 开发的小型快速轻量级的 NoSQL 嵌入式数据库,特性: 无服务器的 NoSQL 文档存储,数据存储在单一文件中类似 MongoDb 的简单 API100% C# ...
- noip2012~2015刷题小记录
2012d1t1 密码 模拟题 #include<cstdio> #include<cstdlib> #include<cstring> #include<c ...