题目和算法在上一篇讲了,这篇用来贴代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
const int maxm = 2000010;
#define lowbit(i) (i & (-i))
int n,m,q,p,t,tot,a[maxn],tt[maxn],use[maxn];
struct ss{
int l,r,val;
}tree[maxm];
struct qq{
int id,x,y,z;
}qes[10010];
int root[maxn],s[maxn],cnt;
int init_hash(){
for(int i = 1; i <= n; i++) tt[i] = a[i];
sort(tt + 1,tt + tot + 1);
int p = unique(tt + 1,tt + tot + 1) - tt - 1;
return p;
}
int Hash(int key){
int d = lower_bound(tt + 1,tt + p + 1,key) - tt;
return d;
}
void init(){
memset(root,0,sizeof(root));
memset(s,0,sizeof(s));
tree[0].l = tree[0].r = tree[0].val = 0;
cnt = tot = 0;
}
void update(int &rt,int l,int r,int k,int v){
tree[++cnt] = tree[rt];
rt = cnt;
tree[rt].val += v;
if(l == r) return;
int mid = l + r >> 1;
if(k > mid) update(tree[rt].r,mid + 1,r,k,v);
else update(tree[rt].l,l,mid,k,v);
}
void modify(int pos,int k,int v){
for(int i = pos; i <= n; i += lowbit(i))
update(s[i],1,p,k,v);
}
void get(int L,int R,int f){
for(int i = R; i >= 1; i -= lowbit(i)){
if(f == 1) use[i] = tree[use[i]].l;
else use[i] = tree[use[i]].r;
}
for(int i = L; i >= 1; i -= lowbit(i)){
if(f == 1) use[i] = tree[use[i]].l;
else use[i] = tree[use[i]].r;
}
}
int ask(int L,int R){
int res = 0,child;
for(int i = R; i >= 1; i -= lowbit(i)){
child = tree[use[i]].l;
res += tree[child].val;
}
for(int i = L; i >= 1; i -= lowbit(i)){
child = tree[use[i]].l;
res -= tree[child].val;
}
return res;
}
int query(int L,int R,int k){
int l = 1,r = p;
int i = root[L],j = root[R];
for(int i = R; i >= 1; i -= lowbit(i)) use[i] = s[i];
for(int i = L; i >= 1; i -= lowbit(i)) use[i] = s[i];
while(l < r){
int mid = l + r >> 1;
int sz = ask(L,R) + tree[tree[j].l].val - tree[tree[i].l].val;
if(sz >= k){ //同时移动到左子树
get(L,R,1);
i = tree[i].l;
j = tree[j].l;
r = mid;
}
else{
k -= sz;
get(L,R,0);
i = tree[i].r;
j = tree[j].r;
l = mid + 1;
}
}
return l;
}
char op[2];
int main(){
int x,y,z;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
tot = n;
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
}
for(int i = 1; i <= m; i++){
scanf("%s",op);
if(op[0] == 'Q'){
qes[i].id = 0;
scanf("%d%d%d",&qes[i].x,&qes[i].y,&qes[i].z);
}
else{
qes[i].id = 1;
scanf("%d%d",&qes[i].x,&qes[i].y);
tt[++tot] = qes[i].y;
}
}
p = init_hash();
for(int i = 1; i <= n; i++){
int mp = Hash(a[i]);
root[i] = root[i - 1];
update(root[i],1,p,mp,1);
}
for(int i = 1; i <= m; i++){
if(qes[i].id == 0){
printf("%d\n",tt[query(qes[i].x - 1,qes[i].y,qes[i].z)]);
}
else{
modify(qes[i].x,Hash(a[qes[i].x]),-1);
modify(qes[i].x,Hash(qes[i].y),1);
a[qes[i].x] = qes[i].y;
}
}
}
return 0;
}
递归(略麻烦的是那个查询左子树右子树这个操作,要操作log(n)棵树)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
const int maxm = 2000010;
#define lowbit(i) (i & (-i))
int n,m,q,p,t,tot,a[maxn],tt[maxn],use[maxn];
struct ss{
int l,r,val;
}tree[maxm];
struct qq{
int id,x,y,z;
}qes[10010];
int root[maxn],s[maxn],cnt;
int init_hash(){
for(int i = 1; i <= n; i++) tt[i] = a[i];
sort(tt + 1,tt + tot + 1);
int p = unique(tt + 1,tt + tot + 1) - tt - 1;
return p;
}
int Hash(int key){
int d = lower_bound(tt + 1,tt + p + 1,key) - tt;
return d;
}
void init(){
memset(root,0,sizeof(root));
memset(s,0,sizeof(s));
tree[0].l = tree[0].r = tree[0].val = 0;
cnt = tot = 0;
}
void update(int &rt,int l,int r,int k,int v){
tree[++cnt] = tree[rt];
rt = cnt;
tree[rt].val += v;
if(l == r) return;
int mid = l + r >> 1;
if(k > mid) update(tree[rt].r,mid + 1,r,k,v);
else update(tree[rt].l,l,mid,k,v);
}
void modify(int pos,int k,int v){
for(int i = pos; i <= n; i += lowbit(i))
update(s[i],1,p,k,v);
}
void get(int L,int R,int f){
for(int i = R; i >= 1; i -= lowbit(i)){
if(f == 1) use[i] = tree[use[i]].l;
else use[i] = tree[use[i]].r;
}
for(int i = L; i >= 1; i -= lowbit(i)){
if(f == 1) use[i] = tree[use[i]].l;
else use[i] = tree[use[i]].r;
}
}
int ask(int L,int R,int f){
int res = 0,child;
for(int i = R; i >= 1; i -= lowbit(i)){
child = tree[use[i]].l;
res += tree[child].val;
}
for(int i = L; i >= 1; i -= lowbit(i)){
child = tree[use[i]].l;
res -= tree[child].val;
}
return res;
}
int query(int ls,int rs,int L,int R,int l,int r,int k){
if(l == r){
return l;
}
int mid = l + r >> 1;
int cur = ask(L,R,1) + tree[tree[rs].l].val - tree[tree[ls].l].val;
if(cur >= k){
get(L,R,1);
return query(tree[ls].l,tree[rs].l,L,R,l,mid,k);
}
else{
get(L,R,0);
return query(tree[ls].r,tree[rs].r,L,R,mid + 1,r,k - cur);
}
}
int Answer(int L,int R,int l,int r,int k){
for(int i = R; i >= 1; i -= lowbit(i)) use[i] = s[i];
for(int i = L; i >= 1; i -= lowbit(i)) use[i] = s[i];
return query(root[L],root[R],L,R,l,r,k);
}
char op[2];
int main(){
int x,y,z;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
tot = n;
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
}
for(int i = 1; i <= m; i++){
scanf("%s",op);
if(op[0] == 'Q'){
qes[i].id = 0;
scanf("%d%d%d",&qes[i].x,&qes[i].y,&qes[i].z);
}
else{
qes[i].id = 1;
scanf("%d%d",&qes[i].x,&qes[i].y);
tt[++tot] = qes[i].y;
}
}
p = init_hash();
for(int i = 1; i <= n; i++){
int mp = Hash(a[i]);
root[i] = root[i - 1];
update(root[i],1,p,mp,1);
}
for(int i = 1; i <= m; i++){
if(qes[i].id == 0){
printf("%d\n",tt[Answer(qes[i].x - 1,qes[i].y,1,p,qes[i].z)]);
}
else{
modify(qes[i].x,Hash(a[qes[i].x]),-1);
modify(qes[i].x,Hash(qes[i].y),1);
a[qes[i].x] = qes[i].y;
}
}
}
return 0;
}