ZOJ - 2112 Dynamic Rankings(BIT套主席树)
纠结了好久的一道题,以前是用线段树套平衡树二分做的,感觉时间复杂度和分块差不多了。。。
终于用BIT套函数式线段树了过了,120ms就是快,此题主要是卡内存。
假设离散后有ns个不同的值,递归层数是log2(ns)左右,nlog(ns),主席树是前缀区间,BIT保存修改的值是mlog2(ns)log2(ns)。
虽然这个算出来还是会爆,但是实际上会有一些结点复用,具体设置多少请相信玄学。(2e6左右)
ZOJ的Node*计算内存似乎有问题,必须用int
/*********************************************************
* ------------------ *
* author AbyssFish *
**********************************************************/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
//#pragma pack(4) const int MAX_N = 5e4+;
const int MAX_M = 1e4+;
const int MAX_NM = MAX_N+MAX_M;
const int MAX_D = ;
const int MAX_ND = 0xac*MAX_M+0x42fed;//MAX_D*MAX_N+MAX_M*MAX_D*MAX_D; int b[MAX_NM];
int mp_a[MAX_NM]; int ns, n_; int N, M; struct Cmd
{
int i, j, k;
}qus[MAX_M]; struct Node
{
int lc, rc;
int s;
}p[MAX_ND]; int root[MAX_N];
int cnt; #define lsn p[o].lc,l,md
#define rsn p[o].rc,md+1,r void build(int x,int &o,int l = , int r = ns)
{
p[++cnt] = p[o];
o = cnt;
p[o].s++;
if(r > l){
int md = (l+r)>>;
if(x <= md) build(x,lsn);
else build(x,rsn);
}
} int BIT[MAX_N]; void inst(int x, int d, int &o, int l = , int r = ns)
{
if(o == ){
p[++cnt] = p[o];
o = cnt;
}
p[o].s += d;
if(l < r){
int md = (l+r)>>;
if(x<=md) inst(x,d,lsn);
else inst(x,d,rsn);
} } #define lowbit(x) ((x)&(-x)) void modify_bit(int pos, int x, int d)
{
while(pos <= N){
inst(x,d,BIT[pos]);
pos += lowbit(pos);
}
} typedef vector<int> Prefix; void prefix_bit(int pos, Prefix &res)
{
res.clear();
while(pos > ){
res.push_back(BIT[pos]);
pos -= lowbit(pos);
}
} inline int cal_lft(Prefix &pfx)
{
int re = ;
for(int i = pfx.size()-; i >= ; i--){
re += p[p[pfx[i]].lc].s;
}
return re;
} #define dump(pfx,ch)\
for(i = pfx.size()-; i >= ; i--){\
pfx[i] = p[pfx[i]].ch;\
} Prefix X, Y; int qkth(int k,int l = , int r = ns)
{
if(l == r) return mp_a[l];
else {
int l_cnt = cal_lft(Y)-cal_lft(X);
int md = (l+r)>>, i;
if(k <= l_cnt){
dump(X,lc)
dump(Y,lc)
return qkth(k,l,md);
}
else {
dump(X,rc)
dump(Y,rc)
return qkth(k-l_cnt,md+,r);
}
} } void solve()
{
cnt = ;
memset(BIT+,,sizeof(int)*N);
int i;
for(i = ; i <= N; i++){
root[i] = root[i-];
build(b[i], root[i]);
} for(i = ; i < M; i++){
if(qus[i].j < ){
int pos = qus[i].i;
modify_bit(pos,b[pos],-);
modify_bit(pos,b[pos] = b[qus[i].k],);
}
else {
int L = qus[i].i-, R = qus[i].j;
prefix_bit(L,X);
prefix_bit(R,Y);
X.push_back(root[L]);
Y.push_back(root[R]);
printf("%d\n",qkth(qus[i].k));
}
}
} int * const a = (int *)(p+);
int * const r = a + MAX_NM; void init()
{
scanf("%d%d",&N,&M);
for(int i = ; i <= N; i++){
scanf("%d",a+i);
r[i] = i;
} n_ = N;
char ch[];
for(int i = ; i < M; i++){
scanf("%s",ch);
if(*ch == 'Q') {
scanf("%d%d%d",&qus[i].i,&qus[i].j,&qus[i].k);
}
else {
qus[i].k = ++n_;
r[n_] = n_;
scanf("%d%d",&qus[i].i,a+n_);
qus[i].j = -;
}
} sort(r+,r+n_+,[](int i,int j){ return a[i]<a[j]; });
mp_a[b[r[]] = ns = ] = a[r[]];
for(int i = ; i <= n_; i++) {
int k = r[i];
if(a[k] != a[r[i-]]){
mp_a[b[k] = ++ns] = a[k];
}
else {
b[k] = ns;
}
}
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
//cout<<ceil(log2(MAX_N+MAX_M))+1;
//cout<<sizeof(Node*)<<endl;
//cout<<MAX_ND<<endl;
// cout<<MAX_ND*sizeof(Node)+(MAX_NM)*16+MAX_M*12+MAX_N*8;
// cout<<sizeof(a)+sizeof(root)+sizeof(meo)+sizeof(qus)+sizeof(BIT)<<endl;//sizeof(b)+sizeof(mp_a)+sizeof(r)
p[] = {,,};
X.reserve(MAX_D+);
Y.reserve(MAX_D+); int T; scanf("%d",&T);
while(T--){
init();
solve();
}
return ;
}
ZOJ - 2112 Dynamic Rankings(BIT套主席树)的更多相关文章
- ZOJ 2112 Dynamic Rankings(二分,树套树)
动态区间询问kth,单点修改. 区间用线段树分解,线段树上每条线段存一颗平衡树. 不能直接得到kth,但是利用val和比val小的个数之间的单调性,二分值.log^3N. 修改则是一次logN*log ...
- bzoj1901: Zju2112 Dynamic Rankings(BIT套主席树)
带修改的题主席树不记录前缀,只记录单点,用BIT统计前缀. 对于BIT上每一个点建一棵主席树,修改和询问的时候用BIT跑,在主席树上做就行了. 3k4人AC的题#256...应该不算慢 #incl ...
- 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )
在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...
- 整体二分&cdq分治 ZOJ 2112 Dynamic Rankings
题目:单点更新查询区间第k大 按照主席树的思想,要主席树套树状数组.即按照每个节点建立主席树,然后利用树状数组的方法来更新维护前缀和.然而,这样的做法在实际中并不能AC,原因即卡空间. 因此我们采用一 ...
- ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)
题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...
- 整体二分(SP3946 K-th Number ZOJ 2112 Dynamic Rankings)
SP3946 K-th Number (/2和>>1不一样!!) #include <algorithm> #include <bitset> #include & ...
- ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解
题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...
- ZOJ 2112 Dynamic Rankings(树状数组+主席树)
题意 \(n\) 个数,\(m\) 个操作,每次操作修改某个数,或者询问某个区间的第 \(K\) 小值. \(1 \leq n \leq 50000\) \(1 \leq m \leq 10000\) ...
- BZOJ 1901 洛谷 P2617 ZOJ 2112 Dynamic Rankings
以下时空限制来自zoj Time limit 10000 ms Memory limit 32768 kB OS Linux Source Online Contest of Christopher' ...
- ZOJ 2112 Dynamic Rankings (动态第k大,树状数组套主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
随机推荐
- 8 Operator overloading
在类中,Groovy支持你使用标准的操作符.例如,如果你想使用a+b操作(a和b来自于Z类),那么你在Z类中,必须实现(implement)plus(Zname)方法.
- Linux ps命令记录
ps命令:查看当前系统进程状态 ps -a 显示当前所有进程ps -ax 显示没有控制终端的进程ps -u better 查看用户better的进程ps aux|less 通过cpu和内存来 ...
- ace+validate表单验证(两种方法)
//修改密码(直接在validate中验证提交) $("#changePassword").on(ace.click_event, function() { var html = ...
- maya2012无法安装卸载激活失败
AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...
- cout和printf不能混用
1.两者的缓存机制不同:printf无缓冲区,而std::cout有 (其实printf也是有缓冲区的,https://blog.csdn.net/ithzhang/article/details/6 ...
- Kure讲HTML_div标签和table标签
为什么要把这两个标签放在一起讲? 个人认为div标签可以算是一个万能标签,它可以通过CSS(层叠样式表)来模仿表格的形式来生成一个表格.那么很多人可能会疑惑那在开发的时候,到底是用div+css的形式 ...
- 安装rails遇到的问题
1 要安装js运行环境,例如Nodejs,如果使用nvm记得,安装完执行nvm use '版本号' 2 或者在Gemfile文件中加入: gem 'execjs'gem 'therubyracer'然 ...
- & 和nohup使用
" & "的使用 将工作丢到背景(这里指的背景并非是系统的背景,指的是在终端模式下,可以避免ctrl+c中断的一个情景)中去执行(但是如果终端关闭时,程序也就退出了,这时 ...
- 关于docker remote api未授权访问漏洞的学习与研究
漏洞介绍: 该未授权访问漏洞是因为docker remote api可以执行docker命令,从官方文档可以看出,该接口是目的是取代docker 命令界面,通过url操作docker. docker ...
- c++ 控制台输入参数
#include <iostream>#include <string> using namespace std; int main(int argc,char **argv) ...