【BZOJ1503】Splay 区间删除 (1)
来源:互联网 发布:手机淘宝无法识别图片 编辑:程序博客网 时间:2024/05/20 23:56
#include <cstdio>#include <cstring>#include <algorithm>#include <climits>#include <iostream>using namespace std;//const int MAXN = 1e5 + 5;int n, minn;int cnt;struct Splay { struct Node { Node *fa, *ch[2], **root; int size, cnt, x; Node(Node **root, Node *fa, int x) : root(root), fa(fa), x(x), size(1), cnt(1) { ch[0] = ch[1] = NULL; } int relation() { return this == fa->ch[1] ? 1 : 0; } void maintain() { size = cnt; if (ch[1]) size += ch[1]->size; if (ch[0]) size += ch[0]->size; } void rotate() { Node *old = fa; int r = relation(); fa = old->fa; if (old->fa) { old->fa->ch[old->relation()] = this; } if (ch[r ^ 1]) { ch[r ^ 1]->fa = old; } old->ch[r] = ch[r ^ 1]; old->fa = this; ch[r ^ 1] = old; old->maintain(); maintain(); if (!fa) { *root = this; } } void splay(Node *target = NULL) { while (fa != target) { if (fa->fa == target) { rotate(); } else if (relation() == fa->relation()) { fa->rotate(); rotate(); } else { rotate(); rotate(); } } } Node *pred() { //求前驱和后继之前必须是根 this->splay(); Node *v = ch[0]; while (v->ch[1]) v = v->ch[1]; return v; } Node *succ() { this->splay(); Node *v = ch[1]; while (v->ch[0]) v = v->ch[0]; return v; } int rank() { return ch[0] ? ch[0]->size : 0; } } *root; Splay() : root(NULL) { insert(INT_MAX); insert(INT_MIN); } Node *insert(int x) { Node **v = &root, *fa = NULL; while ((*v) != NULL && (*v)->x != x) { fa = *v; fa->size++; if (x < fa->x) { v = &fa->ch[0]; } else { v = &fa->ch[1]; } } if ((*v) != NULL) { (*v)->cnt++; (*v)->size++; } else { (*v) = new Node(&root, fa, x); } (*v)->splay(); return root; } Node *find(int x) { Node *v = root; while (v != NULL && v->x != x) { if (x < v->x) { v = v->ch[0]; } else { v = v->ch[1]; } } if (v) v->splay(); return v; } // void erase(Node *v) // { // Node *pred = v->pred(), *succ = v->succ(); // pred->splay(); // succ->splay(pred); // // if (v->cnt > 1) // { // v->size--; // v->cnt--; // } // else // { // delete succ->ch[0]; // succ->ch[0] = NULL; // } // // succ->size--; // pred->size--; // } // // void erase(int x) // { // Node *v = find(x); // // if (!v) return; // erase(v); // } // int rank(int x) // { // Node *v = find(x); // // if (v == NULL) // { // v = insert(x); // int res = v->rank(); // erase(v); // return res; // } // else // { // return v->rank(); // } // } int kth(int k) { Node *v = root; while (!(k >= v->rank() && k < v->rank() + v->cnt)) { if (k < v->rank()) { v = v->ch[0]; } else { k -= v->rank() + v->cnt; v = v->ch[1]; } } v->splay(); return v->x; } // void add(int k, Node *v) // { // v->x += k; // if (v->ch[0]) add(k, v->ch[0]); // if (v->ch[1]) add(k, v->ch[1]); // } void erase(Node *l, Node *r)//删除区间 { Node *pred = l->pred(), *succ = r->succ(); pred->splay(); succ->splay(pred); delete succ->ch[0]; succ->ch[0] = NULL; succ->maintain(); pred->maintain(); } void kill(int l, int r) { Node *vl = find(l), *vr = find(r); if (!vl) vl = insert(l); if (!vr) vr = insert(r); erase(vl, vr); // while (v->ch[1]->x < minn) // { // v = v->ch[1]; // } // // v->splay(); // cnt += v->rank(); // v = v->ch[0]; // // while (v->ch[0] || v->ch[1]) // { // if (v->ch[0]) erase(v->ch[0]); // if (v->ch[1]) erase(v->ch[1]); // } // // // if (v->x < minn) // // { // // if (v->) // // erase(v); // // } // // } int size() { return root->size - 2; }} splay;int main(){ int add = 0; scanf("%d %d", &n, &minn); for (int i = 0; i < n; i++) { //char fu; int k; //cin >> fu >> k; //scanf("%c %d", &fu, &k); // scanf("%c", &fu); // scanf("%d", &k); //这里为什么不能用scanf? char s[2]; scanf("%s %d", s, &k); if (s[0] == 'I') { // if (k < minn) // { // cnt++; // } if (k >= minn) { k -= add; splay.insert(k); } // splay.insert(k); // if (splay.find(k)->x < minn) // { // splay.erase(k); // } } else if (s[0] == 'A') { add += k; //splay.add(k, splay.root); } else if (s[0] == 'S') { add -= k; //splay.add(-k, splay.root); //splay.kill(splay.root); int L = minn; L -= add; //int oldSize = splay.root->size - 2; int oldSize = splay.size(); splay.kill(INT_MIN + 1, L - 1); cnt += oldSize - splay.size(); } else if (s[0] == 'F') { if (k > splay.root->size - 2 || k < 1) { printf("-1\n"); } else { printf("%d\n", splay.kth((splay.root->size - 2) - k + 1) + add); } } } printf("%d\n", cnt); return 0;}
抄了sulfur6【团长的博客!】和Menci两位神犇的代码【也就是说基本上没有我自己写的,我把代码放这主要是想写一些错误啥的!】。感谢!
这道题调的我已经变身郁闷的程序员了好吗qnq
那一条条来说一下我的心(zhi)路(zhang)历程
1)Splay里的while老写成if
2)区间删除我写的奇奇怪怪【就是不会写然后xjb写】最后区间删除的做法和删一个点思想一样,不同的就是是把那个区间而不是一个点转过去【好像有一种把一个区间缩成点的意思?】然后传进去的参数是两个数字,这样很方便。
3)我加工资和减工资一开始都是写的递归下去全改了,然后就是段错误。【我改成打标记就没有段错误了,可能是我递归也写错了吧】【我每次调Splay都会在求前驱和后继那里段错误!每次都会!话说求前驱和后继需要转到根?这个程序里可能在什么我不知道的地方转过去了吧(挠头)我再好好看看(唉还是有不懂的地方啊qnq一知半解的。。。。。)】这是在全局打标记,团长说Menci的是在Splay里打标记 ,我去学!
4)然后减工资踢人的时候就要加上标记的相反数。我一开始想工资下限又没有变,为什么要改?这样想,他们的工资全涨了一个数,但实际上只是标记了一下,没有给他们实际改工资,那这样的话工资下限以下的人要被踢掉【哦不,是辞职】但是按原先的工资下限的话肯定不行,因为这样涨工资之后实际上在工资下限以上的人也会被踢【就这样说吧owo】那就让工资下限降低,他们应该涨多少就工资下限就降多少【就相当于相对运动?你往东走就相当于我往西走这样】BINGO!问题解决!,时间从每次O(n)变成了O(1)【好像是这样,时间复杂度我还不是很会算qnq(托腮)】还有查询的时候要加上标记。
5)改成了和团长的代码差不多一样之后还是过不了样例。把scanf改成cin之后好了很多!(还是过不了。。。)这里我不懂,问了Menci。说是因为scanf(“%c”)会把’\n’和’\0’也读进去(大坑啊)【话说还有两个大坑,知乎回答里说的,if (x = 0) die Gavin;
(hhhhhh顺手黑栋栋(别打我,逃))和int a, b; long long c = a * b;
(然而还是逃脱不了爆int的命运(逃))】Fancy学姐的解决方法是每次读一个字符串(超强!)。开一个char s[2]
用的时候取s[0]就行【这里是char s[数组内的元素个数]
,我还以为开char s[1]
,然后s[0]存字符,s[1]存’\0’就行呢qnq然而事实根本不是我想象的那样(摊手)我果真naive】
6)可是被踢出去的人数还是统计错了,我把求树的大小从每次求改成写在Splay的函数里不知道为什么就对了,我觉得并没有什么区别啊【回来仔细研究系列。。。。】
唉,可是不易= =我一个抄板子都抄不对的废人。。。。。
- 【BZOJ1503】Splay 区间删除 (1)
- BZOJ1503(Splay)
- Splay+BZOJ1503
- bzoj1503 splay
- 【数据结构SPLAY】splay区间翻转,区间和查询,区间插入,区间删除,区间修改
- bzoj1503郁闷的出纳员 Splay
- splay区间翻转及删除区间,平移区间
- 新技能:splay支持区间翻转,区间插入,区间删除
- [BZOJ1503]NOI2004 郁闷的出纳员|splay
- 【bzoj1503】[NOI2004]郁闷的出纳员 Splay
- 【codevs1286】【BZOJ1503】郁闷的出纳员,splay练习
- 【BZOJ1503】[NOI2004]郁闷的出纳员【Splay】
- bzoj1503 [NOI2004]郁闷的出纳员(splay)
- bzoj1503 [NOI2004]郁闷的出纳员 splay
- UVA 11996 Splay + LCP + Hash + 区间翻转 插入 删除
- hdu 3487 Play with Chain splay 区间翻转,插入,删除
- hihoCoder 1333 Splay树(区间求和,区间修改,区间删除,单个增加)
- BZOJ1503
- redis持久化原理详解
- pandas画图
- java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例
- box-sizing:border-box;的一些坑
- Understadning treeReduce() in Spark
- 【BZOJ1503】Splay 区间删除 (1)
- spring 使用get/set注入对象的属性值
- 【BZOJ 2561】最小生成树 最小割
- 数据源
- 如何动态修改log4j2的配置文件路径,并兼容commong logging门面框架
- 5.4.2.1、SSAS-创建计算-同环比
- Kaldi lattices format
- sublime text 3配置c/c++编译环境
- Gson 序列化