我们将线段树套在树状数组上,查询前预处理出所有要一起移动的节点编号,并在查询过程中一起将这些节点移到左右子树上。
Code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 6000000 + 5;
int A[maxn], arr[maxn];
int n, m, cnt;
struct Queries
{
int c, l, r, k;
Queries(int c = 0, int l = 0, int r = 0, int k = 0):c(c), l(l), r(r), k(k) {}
}asks[maxn];
struct Segment_Tree
{
int lson[maxn * 10], rson[maxn * 10], root[maxn], temp[2][200], count[2], sumv[maxn * 10];
int cnt_Tree;
inline int lowbit(int t)
{
return t & (-t);
}
void insert(int l, int r, int pos, int delta, int &o)
{
if(!o) o = ++cnt_Tree;
sumv[o] += delta;
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid)
insert(l, mid, pos, delta, lson[o]);
else
insert(mid + 1, r, pos, delta, rson[o]);
}
inline void update(int pos, int val, int delta)
{
for(int i = pos;i <= n; i += lowbit(i))
insert(1, n, val, delta, root[i]);
}
int query(int l, int r, int k)
{
if(l == r) return l;
int sum = 0;
for(int i = 1;i <= count[0]; ++i) sum += sumv[lson[temp[0][i]]];
for(int i = 1;i <= count[1]; ++i) sum -= sumv[lson[temp[1][i]]];
int mid = (l + r) >> 1;
if(k <= sum) {
for(int i = 1;i <= count[0]; ++i) temp[0][i] = lson[temp[0][i]];
for(int i = 1;i <= count[1]; ++i) temp[1][i] = lson[temp[1][i]];
return query(l, mid, k);
}
else
{
for(int i = 1;i <= count[0]; ++i) temp[0][i] = rson[temp[0][i]];
for(int i = 1;i <= count[1]; ++i) temp[1][i] = rson[temp[1][i]];
return query(mid + 1, r, k - sum);
}
}
inline int Query(int l, int r, int k)
{
memset(temp, 0, sizeof(temp));
count[0] = count[1] = 0;
for(int i = r;i >= 1;i -= lowbit(i))
temp[0][++count[0]] = root[i];
for(int i = l - 1;i >= 1;i -= lowbit(i))
temp[1][++count[1]] = root[i];
return query(1, n, k);
}
}T;
inline int get(int a)
{
return lower_bound(A + 1, A + 1 + cnt, a) - A;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; ++i)
{
scanf("%d",&arr[i]);
A[i] = arr[i];
}
cnt = n;
for(int i = 1;i <= m; ++i)
{
char opt[3];
scanf("%s",opt);
if(opt[0] == 'Q')
{
int a, b, c;
scanf("%d%d%d",&a,&b,&c);
asks[i] = Queries(0, a, b, c);
}
if(opt[0] == 'C')
{
int a, b;
scanf("%d%d",&a,&b);
asks[i] = Queries(1, a, a, b);
A[++cnt] = b;
}
}
n = cnt;
sort(A + 1, A + 1 + cnt);
for(int i = 1;i <= n; ++i)
{
int cur_num = get(arr[i]);
T.update(i, cur_num, 1);
}
for(int i = 1;i <= m; ++i)
{
if(asks[i].c)
{
int origin_num = get(arr[asks[i].l]);
T.update(asks[i].l, origin_num, -1);
int cur_num = get(asks[i].k);
T.update(asks[i].l, cur_num, 1);
arr[asks[i].l] = asks[i].k;
}
else printf("%d\n", A[T.Query(asks[i].l, asks[i].r, asks[i].k)]);
}
return 0;
}

  

最新文章

  1. C# 匿名对象随笔
  2. MyBatis 中 Result Maps collection already contains value for xxx 错误原因
  3. Windows&#174; 10 Mobile Technical Preview升级方法
  4. FinanceJson
  5. 【转】页面跳转Transfer与Redirect的区别你知道吗?
  6. CentOS7 安装 MySQL 5.7.10
  7. Mysql分表教程
  8. Scroll View 控件以Thumbnail的方式显示一个目录的全部图片,相似图片浏览器
  9. ruby web性能响应时间
  10. PAT乙级1034. 有理数四则运算(20)
  11. react-native-upgrade-android
  12. Mapreduce操作HBase
  13. ORM版学员管理系统2
  14. 公共的service接口
  15. Linux内核分析第三周总结
  16. HDU 4737 A Bit Fun (2013成都网络赛)
  17. 系统优化 /etc/sysctl.conf
  18. android 优秀框架整理
  19. 一:Jquery-selector
  20. ubuntu执行级别,设置单用户模式

热门文章

  1. SQL Server-简单查询语句,疑惑篇
  2. 关于优化for循环的注意的事项
  3. Mac 如何寻找Mac自带的IDLE
  4. Python多线程一学就会!
  5. hdu 1693 插头dp入门
  6. 【Python 学习】continue ,break 的使用
  7. [剑指offer] 8+9. 跳台阶+变态跳台阶 (递归 时间复杂度)
  8. 【codeforces 794B】Cutting Carrot
  9. JDBC、事务和连接池
  10. SharePoint 2010 安装教程