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... ------------------------------------- ...
随机推荐
- 在Linux系统的服务器上使用Memtester进行内存压力测试
最近要测试一台机器的整体性能情况,就在google搜索一番,发现这个一个小工具,说是可以进行内存的压力测试,Memtester主要是捕获内存错误和一直处于很高或者很低的坏位, 其测试的主要项目有随机值 ...
- C#学习之泛型
//主函数//主函数里面调用的类都在后面有具体描述 using System; using System.Collections.Generic; using System.Linq; using S ...
- Object.defineProperty 与 属性描述符
为JavaScript对象新增或者修改属性,有两种不同方式:直接使用=赋值或者使用Object.defineProperty 定义,使用后者的话还可以设置属性的描述符. Object.definePr ...
- 异常的概念和Java异常体系结构
一. 异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架, 是Java语言健壮性的一个重要体现. Ja ...
- 知问前端——cookie插件
Cookie是网站用来在客户端保存识别用户的一种小文件.一般可以保存用户登录信息.购物数据信息等一系列微小信息. 一.使用cookie插件 官方网站:http://plugins.jquery.com ...
- 通过.NET客户端异步调用Web API(C#)
在学习Web API的基础课程 Calling a Web API From a .NET Client (C#) 中,作者介绍了如何客户端调用WEB API,并给了示例代码. 但是,那些代码并不是非 ...
- Robot Framework Change chrome language
由于open browser的参数只有一个ff_profile_dir,所以不能指定chrome profile. 只能通过python 传递lang这个参数去改变语言. python: from s ...
- 【LibreOJ】#538. 「LibreOJ NOIP Round #1」数列递推
[题意]LibreOJ [算法]乱搞 [题解]容易发现数列最后一定单调,最后单调递增则最大值赋为最后一个,反之最小值赋为最后一个,然后处理一些细节就可以AC,要注意以下几点: 1.数列连续三项以及数列 ...
- 【51NOD-0】1134 最长递增子序列
[算法]动态规划 [题解]经典模型:最长上升子序列(n log n) #include<cstdio> #include<algorithm> #include<cstr ...
- 在非ARC工程中使用ARC库
选中工程->TARGETS->相应的target然后选中右侧的“Build Phases”,向下就找到“Compile Sources”了.为对应的库文件添加:-fobjc-arc参数即可 ...