bzoj3065: 带插入区间K小值
无聊来写了下
一开始发现树高是O(n)的,然后就MLE了,进去看了下发现没有重构!
看了半天发现调用错了函数
然后进去又发现不满足sz = ch[0]->sz + ch[1]->sz + 1
然而全都是maintain过的啊
发现后来受某个代码的影响
返回重建节点时把引用去掉了
这样这个点的父亲的信息就不对了
又仔细去看了一下那个人为什么这样做没问题
结果他每次都把内存回收了,而且重建的根节点是最后删除第一个拿出来的(然后他竟然用的队列,当我什么都没说,我还是不知道为什么是对的。。)
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
//#include<cassert> using namespace std; #define ALL_VALUE 0, 70000
const int N = + ; int CNT1 = , CNT2 = ; namespace ST {
struct Node *stk[N * ]; int top;
struct Node {
int sz;
Node* ch[]; Node() {}
Node(int sz) : sz(sz) {
ch[] = ch[] = ;
} void *operator new (size_t) {
// if(!++CNT1 % 100000) cerr << CNT1 << endl;
if(top) return stk[top--];
static Node *pis;
static int left = ;
if(!left) left = N, pis = new Node[N] ();
return left--, pis++;
} void operator delete(void *p) {
// ++CNT2;
stk[++top] = (Node*) p;
}
}; #define mid ((l + r) >> 1)
#define ls o->ch[0], l, mid
#define rs o->ch[1], mid + 1, r void insert(Node*& o, int l, int r, int v, int d) {
if(!o) o = new Node();
o->sz += d;
if(l == r) return;
if(v <= mid) insert(ls, v, d);
else insert(rs, v, d);
if(!o->sz) delete o, o = ;
} int query(Node* o, int l, int r, int v) {// <=v µÄÊýµÄ¸öÊý
if(!o) return ;
if(r <= v) return o->sz;
return query(ls, v) + (v > mid ? query(rs, v) : );
} void remove(Node*& o) {
if(!o) return;
remove(o->ch[]);
remove(o->ch[]);
delete o, o = ;
} #undef mid
#undef ls
#undef rs
} int a[N], dep = ; namespace SGT {
struct Node *pis;
struct Node {
int sz, v; Node *ch[];
ST::Node *da; int cmp(int k) const {
int s = ch[]->size() + ;
if(s == k) return -;
return k < s ? : ;
} Node(int v = ) : v(v) {
ch[] = ch[] = ;
da = ;
sz = ;
} int size() const {
return this ? sz : ;
} void maintain() {
sz = ch[]->size() + ch[]->size() + ;
} int query(int k, int v) const {//²éѯ1-kÀï <= vµÄÊýµÄÊýÁ¿
if(!this || !k) return ;
// cerr << ch[0]->size() << endl;
if(ch[]->size() >= k) return ch[]->query(k, v);
return (ch[] ? ST::query(ch[]->da, ALL_VALUE, v) : ) + (this->v <= v) + ch[]->query(k - ch[]->size() - , v);
} void *operator new(size_t) {
return pis++;
}
}*null, *root, pool[N]; Node *rec[N]; int tot; void print(Node *o) {
if(!o) return;
print(o->ch[]);
ST::remove(o->da);
rec[++tot] = o;
print(o->ch[]);
} /*void check(Node *o) {
if(!o) return;
assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1);
check(o->ch[0]);
check(o->ch[1]);
}*/ void rebuild(Node*& o, int l, int r) {
if(l > r) return o = , void();
int mid = (l + r) >> ;
o = rec[mid];
for(int i = l; i <= r; i++) ST::insert(o->da, ALL_VALUE, rec[i]->v, );
rebuild(o->ch[], l, mid - );
rebuild(o->ch[], mid + , r);
o->maintain();
// assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1);
} void build(Node*& o, int l, int r) {
if(l > r) return;
int mid = (l + r) >> ;
o = new Node(a[mid]);
for(int i = l; i <= r; i++) ST::insert(o->da, ALL_VALUE, a[i], );
build(o->ch[], l, mid - );
build(o->ch[], mid + , r);
o->maintain();
} Node*& insert(Node*& o, int k, int x) { // ÔÚµÚx¸öλÖúó²åÈëx
if(!o) {
o = new Node(x);
ST::insert(o->da, ALL_VALUE, x, );
return null;
}
// assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1);
int d = o->ch[]->size() >= k ? : ;
if(d == ) k -= o->ch[]->size() + ;
Node*& res = insert(o->ch[d], k, x);
o->maintain();
ST::insert(o->da, ALL_VALUE, x, );
if(o->ch[d]->size() > o->size() * 0.75) return o;
else return res;
// assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1);
} int modify(Node*& o, int k, int x) {
// assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1);
int d = o->cmp(k), old;
if(d == ) k -= o->ch[]->size() + ;
if(d == -) old = o->v, o->v = x;
else old = modify(o->ch[d], k, x);
ST::insert(o->da, ALL_VALUE, old, -);
ST::insert(o->da, ALL_VALUE, x, );
return old;
} void insert(int k, int x) {
// SGT::check(SGT::root);
Node*& res = insert(root, k, x);
// SGT::check(SGT::root);
if(res != null) {
tot = ;
print(res);
rebuild(res, , tot);
// SGT::check(SGT::root);
}
}
} int query(int l, int r, int k) {
int L = , R = , res = -;
while(L <= R) {
int mid = (L + R) >> ;
int t1 = SGT::root->query(r, mid);
int t2 = SGT::root->query(l - , mid);
if(t1 - t2 >= k) R = mid - , res = mid;
else L = mid + ;
}
return res;
} int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif SGT::pis = SGT::pool; int x, n, m;
scanf("%d", &n); for(int i = ; i <= n; i++) {
scanf("%d", a + i);
} int la = ; SGT::build(SGT::root, , n); scanf("%d", &m);
char opt[]; int y, k, v; for(int i = ; i <= m; i++) {
// if(i == 2859)
// int debug = 1;
// SGT::check(SGT::root); scanf("%s", opt);
if(opt[] == 'Q') {
scanf("%d%d%d", &x, &y, &k);
x ^= la, y ^= la, k ^= la;
printf("%d\n", query(x, y, k));
}else if(opt[] == 'M') {
scanf("%d%d", &x, &v);
x ^= la, v ^= la;
SGT::modify(SGT::root, x, v);
}else {
scanf("%d%d", &x, &v);
x ^= la, v ^= la;
// int last = CNT1; dep = 0;
SGT::insert(x - , v);
// cerr << SGT::root->sz << endl;
// cerr << CNT1 - last << ' ' << dep << endl;
}
} return ;
}
bzoj3065: 带插入区间K小值的更多相关文章
- [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树
刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...
- BZOJ3065 带插入区间K小值 || 洛谷P4278
这是一道让我崩溃的题...... 然鹅洛谷上时限被改然后只有20分......好像所有人都被卡了(雾) 由于替罪羊树不是依靠旋转操作而是依靠暴力重构的方式维护树的平衡,所以我们可以考虑使用替罪羊树套区 ...
- 【函数式权值分块】【块状链表】bzoj3065 带插入区间K小值
显然是块状链表的经典题.但是经典做法的复杂度是O(n*sqrt(n)*log^2(n))的,出题人明确说了会卡掉. 于是我们考虑每个块内记录前n个块的权值分块. 查询的时候差分什么的,复杂度就是O(n ...
- 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树
[BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...
- bzoj 3065: 带插入区间K小值 替罪羊树 && AC300
3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 1062 Solved: 253[Submit][Status] Des ...
- 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树
题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...
- 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树
经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...
- BZOJ 3065 带插入区间K小值(sag套线段树)
3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 4696 Solved: 1527[Submit][Status][Di ...
- 【学习笔记】浅析平衡树套线段树 & 带插入区间K小值
常见的树套树 一般来说,在嵌套数据结构中,线段树多被作为外层结构使用. 但线段树毕竟是 静态 的结构,导致了一些不便. 下面是一个难以维护的例子: 带插入区间 \(k\) 小值问题 来源:Luogu ...
随机推荐
- 三角网格(Triangle Mesh)的理解
最简单的情形,多边形网格不过是一个多边形列表:三角网格就是全部由三角形组成的多边形网格.多边形和三角网格在图形学和建模中广泛使用,用来模拟复杂物体的表面,如建筑.车辆.人体,当然还有茶壶等.图14.1 ...
- __set($key,$values) 和__get($varName) 魔术方法设置读取私有属性
__set($key,$val) 对类内私有属性赋值 作用:对私有属性的处理 当在类外对类内的私有属性赋值时会自动调用此函数 __get($varName) 读取类内私有属性 作用:虽然可以外部访问, ...
- C语言中float,double类型,在内存中的结构(存储方式)
C语言中float,double类型,在内存中的结构(存储方式)从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以doubl ...
- Android多点触摸 与 手势识别
1. 事件类型 MotionEvent.ACTION_DOWN MotionEvent.ACTION_MOVE MotionEvent.ACTION_UP 2. 事件传递 public boolean ...
- 关于python decode()和 encode()
1.先收集一下这几天看到的关于decode()解码和encode()编码的用法 bytes和str是字节包和字符串,python3中会区分bytes和str,不会混用这两个.字符串可以编码成字节包,而 ...
- sql update from 修改一个表的值来自另一个表
假设有桌子表名 icate_table_set(table_id,table_name,table_state_id,store_id), 桌子状态表名icate_table_state(state_ ...
- 使用Python实现Hadoop MapReduce程序
转自:使用Python实现Hadoop MapReduce程序 英文原文:Writing an Hadoop MapReduce Program in Python 根据上面两篇文章,下面是我在自己的 ...
- gridview数据导出到word和excel以及excel的导入
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI ...
- 14.6.7 Configuring the Number of Background InnoDB IO Threads 配置InnoDB IO Threads的数量
14.6.7 Configuring the Number of Background InnoDB IO Threads 配置InnoDB IO Threads的数量 InnoDB 使用后台线程来服 ...
- [LeetCode#12] Roman to Integer
Problem: Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range ...