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 ...
随机推荐
- 输出第N个素数
输出第N个素数 public class FindNthPrime { public static void main(String[] args){ int N = Integer.parseInt ...
- Photon引擎开发实战(1)——Photon 简介
Photon简介 Photon是一套使用广泛的socket server引擎,服务端底层C++编写,客户端C#编写,跨多平台,收费,效率可观的一款引擎.实用上前有九城游戏(原魔兽世界代理),现在笔者发 ...
- (传智博客)tp开发第一天之tp执行流程分析笔记
1.入口文件index.php 2.ThinkPHP/ThinkPHP.php require THINK_PATH.'Common/runtime.php'; 3.ThinkPHP/Common/r ...
- Android 中 View移动总结:ViewDragHelper学习及用法详解
如上图简单呈现出两个方块后,提出一个需求: 1.拖动方块时,方块(即子View)可以跟随手指移动. 2.一个方块移动时,另一个方块可以跟随移动. 3.将方块移动到左边区域(右边区域)后放开(即手指离开 ...
- 【pyhton】import math与import cmath
import math与import cmath分别代表导入math模块和复数math模块 还有一种导入方式是 from math import sqrt 从math中单独导入sqrt 直接可以用sq ...
- 《深入剖析Tomcat》阅读(一)
第一章 一个简单的Web服务器 该应用程序仅接受位于指定目录的静态资源的请求,如HTML文件和图像文件.它也可以将传入的HTTP请求字节流显示到控制台上.但是,它并不发送任何头信息到浏览器,如日期或者 ...
- LeetCode(4) || Longest Palindromic Substring 与 Manacher 线性算法
LeetCode(4) || Longest Palindromic Substring 与 Manacher 线性算法 题记 本文是LeetCode题库的第五题,没想到做这些题的速度会这么慢,工作之 ...
- SpringMVC conflicts with existing, non-compatible bean definition of same name and class 的解决办法
问题起因 最近,项目组的里的同事遇到一个问题,他自己负责的模块,SpringMVC的Controller与其他模块的Controller 类名重名了,导致整个工程都起不来了. 后台报的错误是这样的: ...
- java项目创建和部署
http://www.cnblogs.com/nexiyi/archive/2012/12/28/2837560.html http://dead-knight.iteye.com/blog/1841 ...
- bzoj 1059: [ZJOI2007]矩阵游戏 二分图匹配
1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1891 Solved: 919[Submit][Statu ...