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 ...
随机推荐
- environment与@ConfigurationProperties的关系 加载过程分析
environment是在printBanner之前就初始化好了, 更在context创建之前, 已经加载application-xxxx.properties, System.properties, ...
- linux下lua运行环境安装
1.下载安装包: [root@H0f ~]# wget http://www.lua.org/ftp/lua-5.2.4.tar.gz http://www.lua.org/ftp/lua-5 ...
- SQL Server Reporting Service(SSRS) 第六篇 SSRS 部署总结
前段时间完成了第一批次SSRS报表的开发,本来以为大功已经告成,结果没有想到在整个发布与部署过程中还是遇到了很多的问题,现将这些问题一一列举出来,希望对以后能够有所启发! 1. 关于数据源与数据集的发 ...
- 数据结构---Java---ArrayList
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...
- Silverlight FullScreen 全屏
<UserControl x:Class="FullScreen.MainPage" xmlns="http://schemas.microsoft.com/win ...
- Keepalived & Lvs集群搭建实验
实验拓扑图: 实验原理: Keepalived 是基于 LVS ,并与 LVS 高度融合的 LVS和keepalived的关系:lvs起的是负载均衡功能,而keepalived则是高可用(热 备)的支 ...
- CentOS 6.5 & 7 的网络YUM源配置
中国科技大学CentOS 6.5的网络源 [base]name=CentOS-$releasever - Base#mirrorlist=http://mirrorlist.centos.org/?r ...
- PV、UV、VV,CV的含义
其中VV和CV是播放类指标,PV和UV是浏览类指标. 1. 播放类指标 VV(Video View,播放数),是指在一个统计周期内,视频被打开的次数之和. CV(Connect Views,内容播放数 ...
- [一点一滴.NET]前台线程和后台线程
前台线程和后台线程就是通过线程实例的属性IsBackground=true or false来区分的. 新建一个线程是默认是后台线程. 前台线程全部执行完之后,才退出进程. 进程退出,所有的后台线程全 ...
- The function getUserId must be used with a prefix when a default namespace is not specified 解决办法
The function getUserId must be used with a prefix when a default namespace is not specified 解决方法: 1. ...