之前写线段树套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大 带修改 在线 线段树套平衡树的更多相关文章

  1. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

  2. bzoj 1901: Zju2112 Dynamic Rankings(树套树)

    1901: Zju2112 Dynamic Rankings 经典的带改动求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,并且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过 ...

  3. BZOJ 1901 Zju2112 Dynamic Rankings

    树阵主席设置树.维护间隔动态K大. .. ZOJ到空间太小,太大,仅仅能到BZOJ上交 1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memor ...

  4. BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7143  Solved: 2968[Su ...

  5. Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6471  Solved: 2697[Su ...

  6. Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6321  Solved: 2628[Su ...

  7. bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1] ...

  8. BZOJ 1901: Zju2112 Dynamic Rankings( 树状数组套主席树 )

    裸的带修改主席树.. 之前用BIT套Splay( http://www.cnblogs.com/JSZX11556/p/4625552.html )A过..但是还是线段树好写...而且快(常数比平衡树 ...

  9. BZOJ 1901: Zju2112 Dynamic Rankings( BIT 套 BST )

    BIT 套 splay 其实也是不难...每个 BIT 的结点保存一颗 splay , 询问就二分答案然后判断rank... ------------------------------------- ...

随机推荐

  1. Centos版本6的使用教程

    Centos版本6的使用教程 1.打开VMware workstation 12 PRO 创建新的虚拟机. 2.使用典型类型配置. 3.选择稍后安装操作系统,可以在后面进行安装. 4.选择安装的系统 ...

  2. sql 中sum函数返回null的解决方案

    SUM 是SQL语句中的标准求和函数,如果没有符合条件的记录,那么SUM函数会返回NULL. 但多数情况下,我们希望如果没有符合条件记录的情况下,我们希望它返回0,而不是NULL,那么我们可以使用例如 ...

  3. ACE线程管理机制-并发控制(4)

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/04/581857.html ACE Synchronization类 这一类并发控制对象一般也 ...

  4. bnuoj25660 Two Famous Companies

    题目链接:https://www.bnuoj.com/v3/problem_show.php?pid=25660 这个二分真的是烧脑QAQ,想了一晚上才懂了一个大概. 首先,整体思路是二分,直观上感受 ...

  5. Codeforces Round #530 (Div. 2):D. Sum in the tree (题解)

    D. Sum in the tree 题目链接:https://codeforces.com/contest/1099/problem/D 题意: 给出一棵树,以及每个点的si,这里的si代表从i号结 ...

  6. java线程的基本概念

    进程和线程 进程的诞生 操作系统中有2个任务A,B,任务A先执行,执行到一半需要io,因此要大量时间,在这个时间段内cpu是空闲的,浪费了资源,于是就有进程,当A暂时无法利用cpu,但是又不能销毁时, ...

  7. Django 1.10中文文档-第一个应用Part3-视图和模板

    本教程上接Django 1.10中文文档-第一个应用Part2-模型和管理站点.我们将继续开发网页投票这个应用,主要讲如何创建一个对用户开放的界面. 概览 视图是Django应用中的一“类”网页,它通 ...

  8. mysql 之修改初始密码

    转载自:https://www.cnblogs.com/ivictor/p/5142809.html 为了加强安全性,MySQL5.7为root用户随机生成了一个密码,在error log中,关于er ...

  9. C++学习之路(三):volatile关键字

    volatile是c++中的一个关键字.用volatile修饰的变量,具有三个性质:易变性 (一)易变性: 由于编译器对代码执行的优化,两条赋值语句,下一条语句可能会直接从上一条语句使用的寄存器中取得 ...

  10. Linux_信号与信号量【转】

    转自:http://blog.csdn.net/sty23122555/article/details/51470949 信号: 信号机制是类UNIX系统中的一种重要的进程间通信手段之一.我们经常使用 ...