主席树模板求不带修改的区间k大
2016-07-06 08:14
330 查看
现在会主席树是不是晚了点。主席树的牛逼就是公用了节点然后因为类似前缀和(其实可以叫做时间前缀和)所以节点可以拿来相减。然后就十分玄妙了。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = (int)3e6 + 10;
const int maxn = (int)1e5;
int lson
, rson
, sum
;
int Time
, total;
int s
, X
;
void PushUp(int rt){
sum[rt] = sum[lson[rt]] + sum[rson[rt]];
}
int build(int L, int R){
int now = ++total;
if (L == R){
lson[now] = rson[now] = 0;
sum[now] = 0;
return now;
}
int m = (L + R) >> 1;
lson[now] = build(L, m);
rson[now] = build(m + 1, R);
PushUp(now);
return now;
}
int update(int rt, int pos, int L, int R){
int now = ++total;
if (L == R){
sum[now] = sum[rt] + 1;
lson[now] = rson[now] = 0;
return now;
}
int m = (L + R) >> 1;
if (pos <= m){
lson[now] = update(lson[rt], pos, L, m);
rson[now] = rson[rt];
}else{
rson[now] = update(rson[rt], pos, m+ 1, R);
lson[now] = lson[rt];
}
PushUp(now);
return now;
}
int ask(int rt1, int rt2, int k, int L, int R){
if (L == R) return X[L];
int number = sum[lson[rt2]] - sum[lson[rt1]];
int m = (L + R) >> 1;
if (number >= k)
return ask(lson[rt1], lson[rt2], k, L, m);
else
return ask(rson[rt1], rson[rt2], k - number, m +1, R);
}
int main(){
int cs; scanf("%d", &cs);
int n, m;
while(cs--){
scanf("%d%d", &n, &m);
int cnt = 0;
for (int i = 1; i <= n; i++){
scanf("%d", &s[i]);
X[++cnt] = s[i];
}
sort(X + 1, X + 1 + cnt);
int all = 1;
for (int i = 2; i <= cnt; i++)
if (X[i] != X[i - 1]) X[++all] = X[i];
total = 0;
Time[0] = build(1, all);
for (int i = 1; i <= n; i++){
int pos = lower_bound(X + 1, X + 1 + all, s[i]) - X;
Time[i] = update(Time[i - 1], pos, 1, all);
}
while(m--){
int L, R, k;
scanf("%d%d%d", &L, &R, &k);
printf("%d\n", ask(Time[L - 1], Time[R], k, 1, all));
}
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = (int)3e6 + 10;
const int maxn = (int)1e5;
int lson
, rson
, sum
;
int Time
, total;
int s
, X
;
void PushUp(int rt){
sum[rt] = sum[lson[rt]] + sum[rson[rt]];
}
int build(int L, int R){
int now = ++total;
if (L == R){
lson[now] = rson[now] = 0;
sum[now] = 0;
return now;
}
int m = (L + R) >> 1;
lson[now] = build(L, m);
rson[now] = build(m + 1, R);
PushUp(now);
return now;
}
int update(int rt, int pos, int L, int R){
int now = ++total;
if (L == R){
sum[now] = sum[rt] + 1;
lson[now] = rson[now] = 0;
return now;
}
int m = (L + R) >> 1;
if (pos <= m){
lson[now] = update(lson[rt], pos, L, m);
rson[now] = rson[rt];
}else{
rson[now] = update(rson[rt], pos, m+ 1, R);
lson[now] = lson[rt];
}
PushUp(now);
return now;
}
int ask(int rt1, int rt2, int k, int L, int R){
if (L == R) return X[L];
int number = sum[lson[rt2]] - sum[lson[rt1]];
int m = (L + R) >> 1;
if (number >= k)
return ask(lson[rt1], lson[rt2], k, L, m);
else
return ask(rson[rt1], rson[rt2], k - number, m +1, R);
}
int main(){
int cs; scanf("%d", &cs);
int n, m;
while(cs--){
scanf("%d%d", &n, &m);
int cnt = 0;
for (int i = 1; i <= n; i++){
scanf("%d", &s[i]);
X[++cnt] = s[i];
}
sort(X + 1, X + 1 + cnt);
int all = 1;
for (int i = 2; i <= cnt; i++)
if (X[i] != X[i - 1]) X[++all] = X[i];
total = 0;
Time[0] = build(1, all);
for (int i = 1; i <= n; i++){
int pos = lower_bound(X + 1, X + 1 + all, s[i]) - X;
Time[i] = update(Time[i - 1], pos, 1, all);
}
while(m--){
int L, R, k;
scanf("%d%d%d", &L, &R, &k);
printf("%d\n", ask(Time[L - 1], Time[R], k, 1, all));
}
}
return 0;
}
相关文章推荐
- VC++的使用
- NOIP 2010 关押罪犯
- 勾股定理一日一证连载44
- iOS Socket介绍及其简单应用
- 动态凸包 学习总结
- LeetCode - 345. Reverse Vowels of a String
- javascript策略模式(strategy)
- 年月日三级联动(纯JS)
- matlab自学经验成果分享 判断变量是否为指定类型
- 新建Android一个项目-菜鸟篇
- 版本工具管理之----git
- matlab自学经验成果分享 字符串的截取
- poj1190 生日蛋糕
- 基于Matlab的自动控制原理 由开环传递函数画出奈奎斯曲线
- 基于Matlab的自动控制原理 由传递函数画出bode图(幅频特性曲线)
- 基于Matlab的自动控制原理 两个传递函数并联
- 基于Matlab的自动控制原理 在根轨迹图上通过鼠标点击得知该点的k与特征根
- 基于Matlab的自动控制原理 已知传递函数,求其阶跃响应
- 基于Matlab的自动控制原理 根据传递函数画根轨迹
- 基于Matlab的自动控制原理 消除相同的零极点因子