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 ...
随机推荐
- Microsoft Windows 远程权限提升漏洞(CVE-2013-3175)(MS13-062)
漏洞版本: Microsoft Windows XP Microsoft Windows Vista Microsoft Windows Server 2008 Microsoft Windows R ...
- java 去掉字符串右侧空格
public static String rightTrim(String str) { String regex = "(.*\\S+)(\\s+$)"; Patte ...
- 网络流(最大流)CodeForces 512C:Fox And Dinner
Fox Ciel is participating in a party in Prime Kingdom. There are n foxes there (include Fox Ciel). T ...
- HDU-2126 Buy the souvenirs
数组01背包. http://acm.hdu.edu.cn/showproblem.php?pid=2126 http://blog.csdn.net/crazy_ac/article/details ...
- java 对list进行排序
前提: list中的元素是自定义对象,如何根据对象的元素进行排序呢? 比如List<Student>students 是一个list,每个元素都是Student对象,Student对象中有 ...
- HDOJ 2011 多项式求和
Problem Description 多项式的描述如下: 1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + - 现在请你求出该多项式的前n项的和. Input 输入数据由2行组成, ...
- SDN基础理解
本文转载自:http://blog.csdn.net/freezgw1985/article/details/16873677 个人觉得对很适合对SDN的入门级的概念性理解,先暂时copy一下,等研究 ...
- qut训练题解-2016-9-4个人赛
题目链接:http://acm.hust.edu.cn/vjudge/contest/131124#overview 贴了链接这里就不上原题的描述了. A: B: 分析:这里用到简单的拓扑排序的算法. ...
- 如何以非 root 用户将应用绑定到 80 端口-ssh 篇 » 社区 » Ruby China
如何以非 root 用户将应用绑定到 80 端口-ssh 篇 » 社区 » Ruby China 如何以非 root 用户将应用绑定到 80 端口-ssh 篇
- The Fortified Forest - POJ 1873(状态枚举+求凸包周长)
题目大意:有个国王他有一片森林,现在他想从这个森林里面砍伐一些树木做成篱笆把剩下的树木围起来,已知每个树都有不同的价值还有高度,求出来砍掉那些树可以做成篱笆把剩余的树都围起来,要使砍伐的树木的价值最小 ...