题目链接:BZOJ - 3196

题目分析

区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现。

为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过128MB = =

嗯就是这样,代码长度= =我写了260行......Debug了n小时= =

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
using namespace std; const int MaxN = 50000 + 5, MaxM = 50000 + 5, MN = 100000 + 15, INF = 999999999, MaxNode = 8000000 + 15; int n, m, Index, Used_Index, Top, Hash_Index;
int A[MaxN], Root[MaxN], T[MaxNode], Son[MaxNode][2], U[MaxN], C[MaxN], Que[MaxN + MaxM], TR[MaxN + MaxM]; struct Query
{
int f, L, R, k, Num, Pos;
} Q[MaxM]; map<int, int> M; multiset<int> S[MaxN * 4];
multiset<int>::iterator It; inline int gmin(int a, int b) {return a < b ? a : b;}
inline int gmax(int a, int b) {return a > b ? a : b;} void Add(int &x, int s, int t, int Pos, int Num)
{
if (x == 0) x = ++Index;
T[x] += Num;
if (s == t) return;
int m = (s + t) >> 1;
if (Pos <= m) Add(Son[x][0], s, m, Pos, Num);
else Add(Son[x][1], m + 1, t, Pos, Num);
} void Change(int x, int Pos, int Num)
{
for (int i = x; i <= n; i += i & -i)
Add(Root[i], 0, MN, Pos, Num);
} void Add_S(int x, int s, int t, int Pos, int Num)
{
S[x].insert(Num);
if (s == t) return;
int m = (s + t) >> 1;
if (Pos <= m) Add_S(x << 1, s, m, Pos, Num);
else Add_S(x << 1 | 1, m + 1, t, Pos, Num);
} void Del_S(int x, int s, int t, int Pos, int Num)
{
S[x].erase(S[x].find(Num));
if (s == t) return;
int m = (s + t) >> 1;
if (Pos <= m) Del_S(x << 1, s, m, Pos, Num);
else Del_S(x << 1 | 1, m + 1, t, Pos, Num);
} void Init_U(int x)
{
for (int i = x; i; i -= i & -i)
U[i] = Root[i];
} void Turn(int x, int f)
{
for (int i = x; i; i -= i & -i)
{
if (C[i] == Used_Index) break;
C[i] = Used_Index;
U[i] = Son[U[i]][f];
}
} int Get_LSum(int x)
{
int ret = 0;
for (int i = x; i; i -= i & -i)
ret += T[Son[U[i]][0]];
return ret;
} int Before(int x, int s, int t, int l, int r, int Num)
{
int ret;
if (l <= s && r >= t)
{
It = S[x].end();
It--;
if (*It < Num) return *It;
It = S[x].begin();
if (*It >= Num) return -INF;
It = S[x].lower_bound(Num);
It--;
return *It;
}
int m = (s + t) >> 1;
ret = -INF;
if (l <= m) ret = gmax(ret, Before(x << 1, s, m, l, r, Num));
if (r >= m + 1) ret = gmax(ret, Before(x << 1 | 1, m + 1, t, l, r, Num));
return ret;
} int After(int x, int s, int t, int l, int r, int Num)
{
int ret;
if (l <= s && r >= t)
{
It = S[x].upper_bound(Num);
if (It == S[x].end()) return INF;
else return *It;
}
int m = (s + t) >> 1;
ret = INF;
if (l <= m) ret = gmin(ret, After(x << 1, s, m, l, r, Num));
if (r >= m + 1) ret = gmin(ret, After(x << 1 | 1, m + 1, t, l, r, Num));
return ret;
} int main()
{
scanf("%d%d", &n, &m);
Top = 0; Index = 0;
for (int i = 1; i <= n; ++i)
{
scanf("%d", &A[i]);
Que[++Top] = A[i];
}
for (int i = 1; i <= m; ++i)
{
scanf("%d", &Q[i].f);
switch (Q[i].f)
{
case 1 :
scanf("%d%d%d", &Q[i].L, &Q[i].R, &Q[i].Num);
break;
case 2 :
scanf("%d%d%d", &Q[i].L, &Q[i].R, &Q[i].k);
break;
case 3 :
scanf("%d%d", &Q[i].Pos, &Q[i].Num);
break;
case 4 :
scanf("%d%d%d", &Q[i].L, &Q[i].R, &Q[i].Num);
break;
case 5 :
scanf("%d%d%d", &Q[i].L, &Q[i].R, &Q[i].Num);
break;
}
if (Q[i].f != 2) Que[++Top] = Q[i].Num;
}
sort(Que + 1, Que + Top + 1);
Hash_Index = 0;
for (int i = 1; i <= Top; ++i)
{
if (i > 1 && Que[i] == Que[i - 1]) continue;
M[Que[i]] = ++Hash_Index;
TR[Hash_Index] = Que[i];
}
for (int i = 1; i <= n; ++i)
{
A[i] = M[A[i]];
Change(i, A[i], 1);
Add_S(1, 1, n, i, A[i]);
}
int L, R, Pos, Num, k, Temp, l, r, mid;
for (int i = 1; i <= m; ++i)
{
if (Q[i].f != 2) Q[i].Num = M[Q[i].Num];
switch (Q[i].f)
{
case 1 :
L = Q[i].L; R = Q[i].R; Num = Q[i].Num;
Used_Index = 0;
Init_U(L - 1);
Init_U(R);
Temp = 0;
l = 0; r = MN;
while (l < r)
{
++Used_Index;
mid = (l + r) >> 1;
if (Num <= mid)
{
r = mid;
Turn(L - 1, 0);
Turn(R, 0);
}
else
{
Temp += Get_LSum(R) - Get_LSum(L - 1);
l = mid + 1;
Turn(L - 1, 1);
Turn(R, 1);
}
}
printf("%d\n", Temp + 1);
break; case 2 :
L = Q[i].L; R = Q[i].R; k = Q[i].k;
Init_U(L - 1);
Init_U(R);
Used_Index = 0;
Temp = 0;
l = 0; r = MN;
while (l < r)
{
++Used_Index;
mid = (l + r) >> 1;
Temp = Get_LSum(R) - Get_LSum(L - 1);
if (Temp >= k)
{
r = mid;
Turn(L - 1, 0);
Turn(R, 0);
}
else
{
l = mid + 1;
Turn(L - 1, 1);
Turn(R, 1);
k -= Temp;
}
}
printf("%d\n", TR[l]);
break; case 3 :
Pos = Q[i].Pos; Num = Q[i].Num;
Change(Pos, A[Pos], -1);
Del_S(1, 1, n, Pos, A[Pos]);
A[Pos] = Num;
Change(Pos, Num, 1);
Add_S(1, 1, n, Pos, Num);
break; case 4 :
L = Q[i].L; R = Q[i].R; Num = Q[i].Num;
printf("%d\n", TR[Before(1, 1, n, L, R, Num)]);
break; case 5 :
L = Q[i].L; R = Q[i].R; Num = Q[i].Num;
printf("%d\n", TR[After(1, 1, n, L, R, Num)]);
break;
}
}
return 0;
}

  

[BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】的更多相关文章

  1. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  2. bzoj3196 二逼平衡树 树状数组套线段树

    题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...

  3. bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Stat ...

  4. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  5. BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...

  6. 洛谷P3380 【模板】二逼平衡树(树套树,树状数组,线段树)

    洛谷题目传送门 emm...题目名写了个平衡树,但是这道题的理论复杂度最优解应该还是树状数组套值域线段树吧. 就像dynamic ranking那样(蒟蒻的Sol,放一个link骗访问量233) 所有 ...

  7. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  8. [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)

    [BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...

  9. luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)

    带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...

随机推荐

  1. linux下so动态库一些不为人知的秘密 系列

    http://blog.chinaunix.net/uid-27105712-id-3313293.html http://www.cnblogs.com/gulvzhe/archive/2012/0 ...

  2. Load Balance Tomcat with Nginx and Store Sessions in Redis--reference

    An awkward title, but that’s exactly what we’re going to do. For some time, I was looking for a way ...

  3. 3行3列表格 table实现,div+css实现

    table实现: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  4. webservice 生成代理类

    webservice的调用方式有两种: 1. 直接在vs ide中通过web引用的方式,将发布于某个位置的web服务引进到工程里面.这种方式基本上会用vs.net的人都会.   2. 通过vs 命令提 ...

  5. 20个命令行工具监控 Linux 系统性能(转载)

    1. top — Linux 系统进程监控 top 命令是性能监控程序,它可以在很多 Linux/Unix 版本下使用,并且它也是 Linux 系统管理员经常使用的监控系统性能的工具.Top 命令可以 ...

  6. 移动设备日期选择插件(基于JQUERY)

    上周花了2个小时写的一个日期选择插件,比较适合移动端的设备.先看个效果图吧.如果刚好是你需要的就往下吧,不需要的也可以继续..... 其实网络上已经有的了类似的成熟插件,比如基于mobiscroll, ...

  7. css中判断IE版本的语句

    css中判断IE版本的语句<!--[if gte IE 6]> Only IE 6/+ <![endif]-->: 1. <!--[if !IE]> 除IE外都可识 ...

  8. git warning: LF will be replaced by CRLF in 解决办法

    在使用git的时候,每次执行 #git add "目录" git add . 都会提示这样一个警告消息: warning: LF will be replaced by CRLF  ...

  9. java 内部类学习

    类和内部类的关系就如同人和心脏的关系. 实例1:内部类的基本结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 //外部 ...

  10. 学习java随笔第九篇:java异常处理

    在java中的异常处理和c#中的异常处理是一样的都是用try-catch语句. 基本语法如下 try { //此处是可能出现异常的代码 } catch(Exception e) { //此处是如果发生 ...