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 ...
随机推荐
- bzoj3261
xor有一个很重要的性质就是A xor B xor B=A所以这道题求[l,r]中p,使a[p] xor a[p+1] xor ... xor a[N] xor x 最大就是=最大化a[1] xor ...
- PHP 不安全文件权限漏洞
漏洞名称: PHP 不安全文件权限漏洞 CNNVD编号: CNNVD-201309-056 发布时间: 2013-09-09 更新时间: 2013-09-09 危害等级: 漏洞类型: 权限许可和 ...
- Light OJ 1050 - Marbles(概率DP)
题目大意: 一个包裹里有蓝色和红色的弹珠,在这个包裹里有奇数个弹珠,你先走, 你先从背包里随机的拿走一个弹珠,拿走每个弹珠的可能性是一样的.然后Jim从背包里拿走一个蓝色的弹珠,如果没有蓝色的弹珠让J ...
- senrty 配置Email
测试页面在这里 右上角头像->管理->邮件 配置如下:(注意一点:465是SSL的 587是TLS的) 其他django email 1.3 文献在这里 现在都1.8了貌似 如 ...
- 关于响应事件中的Sender
很多响应事件都会有个参数就是Sender,如下: - (IBAction)updateSliderValue:(id)sender Sender其实就是触发响应的那个实例对象,比如这个消息是由一个UI ...
- openStack opts
- 600字读懂 Git
译注:来自 Hacker School 的 Mary Rose Cook 实现了一个纯 JavaScript 写就的 Git:Gitlet,包含了最主要的一些命令.这个项目一是为了了解 Git 内部原 ...
- poj 1287 Networking【最小生成树prime】
Networking Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 7321 Accepted: 3977 Descri ...
- liststack——链表栈(procedure)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "list.h&q ...
- 银联手机支付(.Net Csharp),3DES加密解密,RSA加密解密,RSA私钥加密公钥解密,.Net RSA 3DES C#
前段时间做的银联支付,折腾了好久,拼凑的一些代码,有需要的朋友可以参考,本人.Net新手,不保证准确性! 这个银联手机支付没有SDK提供,技术支持也没有.Net的,真心不好搞! RSA加解密,这里有个 ...