ZOJ2112 Dynamic Rankings 动态区间第K最值 平方分割
有了上一题的经验(POJ的静态区间第K最值)再解决这道题就轻松多了
空间5256KB,时间3330ms,如果把动态开点的平衡树换成数组模拟的话应该会更快
之所以选择了平方分割而不是树套树,不仅是所谓趁热打铁,更是因为:
平方分割的修改操作,无论编程复杂度还是时间复杂度都远优于树套树。
代码如下:(鄙人不才,不会压代码,所以写了300多行Σ( ° △ °|||)
template <class T> struct SbtNode { typedef SbtNode<T> Node; Node* lch; Node* rch; T val; int lSize; int rSize; SbtNode(const T& _val): lch(),rch(),val(_val),lSize(),rSize() {} void assign(const T& _val) { lch=rch=; val=_val; lSize=rSize=; } }; template <class T,class Comp> struct SizeBlcTree { ,Left=,Right= }; typedef SbtNode<T> Node; typedef SizeBlcTree<T,Comp> Sbt; Node* root; Comp cmp; SizeBlcTree():root() {} ~SizeBlcTree() { clear(); } void clear_aux(Node* _cur) { if(_cur->lch) clear_aux(_cur->lch); if(_cur->rch) clear_aux(_cur->rch); delete _cur; } void clear() { if(root) clear_aux(root); root=; } Node* lRotate(Node* _cur) { Node* next=_cur->rch; _cur->rch=next->lch; next->lch=_cur; _cur->rSize=next->lSize; next->lSize+=(_cur->lSize+); return next; } Node* rRotate(Node* _cur) { Node* next=_cur->lch; _cur->lch=next->rch; next->rch=_cur; _cur->lSize=next->rSize; next->rSize+=(_cur->rSize+); return next; } Node* insert_aux(const T& _val,Node* _cur) { if(!_cur) return new Node(_val); if(cmp(_val,_cur->val)) { ++_cur->lSize; _cur->lch=insert_aux(_val,_cur->lch); if(_cur->lch->lSize > _cur->rSize) return rRotate(_cur); else if(_cur->lch->rSize > _cur->rSize) { _cur->lch=lRotate(_cur->lch); return rRotate(_cur); } else return _cur; } else { ++_cur->rSize; _cur->rch=insert_aux(_val,_cur->rch); if(_cur->rch->rSize > _cur->lSize) return lRotate(_cur); else if(_cur->rch->lSize > _cur->lSize) { _cur->rch=rRotate(_cur->rch); return lRotate(_cur); } else return _cur; } } Sbt& operator << (const T& _val) { root=insert_aux(_val,root); return *this; } Node* erase_aux(const T& _val,Node* _cur,bool& _found) { if(!_cur) { _found=false; ; } if(cmp(_val,_cur->val)) { _cur->lch=erase_aux(_val,_cur->lch,_found); if(_found) --_cur->lSize; return _cur; } if(cmp(_cur->val,_val)) { _cur->rch=erase_aux(_val,_cur->rch,_found); if(_found) --_cur->rSize; return _cur; } _found=true; ; ; ; Node* res; Node* &prev=res; switch(status) { : delete _cur; ; : res=_cur->lch; delete _cur; return res; : res=_cur->rch; delete _cur; return res; : prev=_cur; if(prev->rch->lch) { --prev->rSize; prev=prev->rch; while(prev->lch->lch) { --prev->lSize; prev=prev->lch; } _cur->val=prev->lch->val; prev->lch=erase_aux(prev->lch->val,prev->lch,_found); --prev->lSize; } else { _cur->val=_cur->rch->val; _cur->rch=erase_aux(_cur->rch->val,_cur->rch,_found); --_cur->rSize; } return _cur; } } Sbt& operator >> (const T& _val) { bool found=false; root=erase_aux(_val,root,found); return *this; } int notMoreCount(const T& _val) { Node* cur=root; ; while(cur) { if(cmp(_val,cur->val)) cur=cur->lch; else { res+=(cur->lSize+); cur=cur->rch; } } return res; } int lessCount(const T& _val) { Node* cur=root; ; while(cur) { if(cmp(cur->val,_val)) { res+=(cur->lSize+); cur=cur->rch; } else cur=cur->lch; } return res; } }; ; ; ; ; #include <functional> #include <algorithm> int unOrd[bktCount*bktSize]; using std::less; SizeBlcTree<int,less<int> > all; SizeBlcTree<int,less<int> > bucket[bktCount]; int N,K; int cs; #include <cstdio> void init() { scanf("%d%d",&N,&K); ;i<N;i++) { scanf("%d",unOrd+i); all<<unOrd[i]; bucket[i>>bktDigit] << unOrd[i]; } } inline void enumerate(int _rL,int _rR,int _val,int& _less,int& _notMore) { for(int i=_rL;i<=_rR;i++) if(unOrd[i]<=_val) { _notMore++; if(unOrd[i]<_val) _less++; } } int getAns(int _rL,int _rR,int _k) { int bktL = _rL>>bktDigit; int bktR = _rR>>bktDigit; int prevVal; SbtNode<int> *cur=all.root; while(cur) { ; ; if(bktL==bktR) enumerate(_rL,_rR,cur->val,less,notMore); else { ;i<bktR;i++) { notMore += bucket[i].notMoreCount(cur->val); less += bucket[i].lessCount(cur->val); } enumerate(_rL,((bktL+)<<bktDigit)-,cur->val,less,notMore); enumerate(bktR<<bktDigit,_rR,cur->val,less,notMore); } if(less<_k && notMore>=_k) return cur->val; prevVal=cur->val; if(less>=_k) cur=cur->lch; else cur=cur->rch; } return prevVal; } void solve() { char cmd; do cmd=getchar(); while(cmd==' ' || cmd=='\n'); if(cmd=='Q') { int rL,rR,k; scanf("%d%d%d",&rL,&rR,&k); printf(,rR-,k)); } else { int pos,v; scanf("%d%d",&pos,&v); --pos; all<<v; bucket[pos>>bktDigit] >> unOrd[pos]; bucket[pos>>bktDigit] << (unOrd[pos]=v) ; } } void reset() { all.clear(); int used=N>>bktDigit; ;i<=used;i++) bucket[i].clear(); } int main() { scanf("%d",&cs); while(cs--) { init(); while(K--) solve(); reset(); } ; }
简析:
可以和我的这篇随笔进行对比:http://www.cnblogs.com/Onlynagesha/p/5353531.html
前面将近2/3都是SBT的模板
平方分割的大致思路和静态第k大是一样的,中间分块高效维护,然后枚举两边的零头
但在动态第k大问题中,每个桶维护的都是一棵平衡树。这样我们便可以高效的修改。
若要进行高效的二分,我们还要维护一颗“总的”平衡树all,存放当前所有的数值。
二分的时候从all的根节点开始,边界是走到叶子节点。二分的每一步都有三种可能:
(1)当前节点就是答案
(2)当前节点的值过大,那么取下一个值为其左孩子
(3)当前节点的值过大,那么取下一个值为其右孩子
注意体会基于树的二分和基于区间的二分的差异。前者难以保证“可能”会成为答案的值被保留(因为每走一步当前的值就被“丢弃”了),而后者可以
另外维护all的时候还有一个小技巧:修改数值时只需将新值插入而不需将旧值删去,这样可以省下一点时间常数
被“删去”的值在之后的二分过程中一定不会满足第(1)种可能
ZOJ2112 Dynamic Rankings 动态区间第K最值 平方分割的更多相关文章
- POJ2104 K-th Number 静态区间第k最值 平方分割
干掉这道题的那一刻,我只想说:我终于**的AC了!!! 最终内存1344K,耗时10282ms,比起归并树.划分树以及其他各种黑科技,这个成绩并不算光彩⊙﹏⊙ 但至少,从最初的无数次TLE到最终的AC ...
- ZOJ2112--Dynamic Rankings (动态区间第k大)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1901 首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊. ...
- 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树套树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1901 这题调了我相当长的时间,1wa1a,我是第一次写树套树,这个是树状数组套splay,在每个区间 ...
- Dynamic Rankings || 动态/静态区间第k小(主席树)
JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...
- ZOJ 1112 Dynamic Rankings【动态区间第K大,整体二分】
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112 题意: 求动态区间第K大. 分析: 把修改操作看成删除与增加 ...
- bzoj1901&zoj2112&cogs257 Dynamic Rankings(动态排名系统)
bzoj1901&zoj2112&cogs257 Dynamic Rankings(动态排名系统) cogs zoj bzoj-权限 题解 bzoj和zoj都是骗访问量的233,我没有 ...
- 主席树--动态区间第k小
主席树--动态区间第\(k\)小 模板题在这里洛谷2617. 先对几个问题做一个总结: 阅读本文需要有主席树的基础,也就是通过区间kth的模板题. 静态整体kth: sort一下找第k小,时间复杂度\ ...
- ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)
题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...
随机推荐
- 【转】MFC获取程序目录路径方法
原文网址:http://yeahyuanqing.blog.163.com/blog/static/118025091201149480818/ MFC获得当前应用程序目录的GetCurrentDir ...
- MySQL中的类Decode用法
SELECT DISTINCT ( CASE ' THEN '关羽' ' THEN ' 张飞' ' THEN ' 赵云' ' THEN ' 马超' ' THEN ' 黄忠' ' THEN ' 魏延' ...
- StoryBoard 的使用
简单入门: http://my.oschina.net/plumsoft/blog/53886 详细操作:http://www.cnblogs.com/buro79xxd/archive/2012/0 ...
- JavaScript高级程序设计10.pdf
String类型有几种操作字符串的方法 concat()方法拼接任意多个字符串,不修改原字符串 var stringValue=“hello ”; var result=stringValue.con ...
- 关于ATL的rgs注册文件
转自:http://blog.csdn.net/idiszerg/article/details/3875934 使用ATL向导的话,会在resource中产生一个rgs的注册脚本文件放在" ...
- verilog 双向IO实现
网上搜索了一番,示例挺多,但发现都写的是 input in; output out; 然后 assign io= (oe)?out:1'bz;就有点想不明白了,当IO方向为输出时,应该输出out的值 ...
- dp poj 1080 Human Gene Functions
题目链接: http://poj.org/problem?id=1080 题目大意: 给两个由A.C.T.G四个字符组成的字符串,可以在两串中加入-,使得两串长度相等. 每两个字符匹配时都有个值,求怎 ...
- 应用360云盘与SVN版本管理服务器搭建基于云端的版本控制软件
步骤一:(安装软件) 1.TortoiseSVN 2.VisualSVN-Server-2.71 3.安装云盘客户端360wangpan_setup 步骤二:(VisualSVN Server设置) ...
- java实现url转码、解码
URL由来: 一般来说,URL只能使用英文字母.阿拉伯数字和某些标点符号,不能使用其他文字和符号.比如,世界上有英文字母的网址 “http://www.abc.com”,但是没有希腊字母的网址“htt ...
- 【Android - 框架】之Glide的使用
一.Glide简介: Glide是Google官方推荐的一个图片加载和缓存的开源库,它不仅能实现平滑的图片列表滚动效果,还支持远程图片的获取.大小调整和展示,并且可以加载GIF图片.Glide相比与U ...