【题目地址】点击打开链接
【分析】
法一:
其实就是在静态区间k小的基础上,利用了树状数组的思想。然后利用sz的可加性,用l-1,r的版本来维护一个区间[l,r]的sz。
其实每个节点用一般的线段树即可,只需要注意动态添点避免爆空间,但我懒得写了,就用可持久化水过了。
法二:
借用上面的方法,进行优化。树状数组套Trie树,这样不仅常数暴小,而且如果数字太大还可以免除离散化操作。
【代码】
法一:
/****************************
ID:Ciocio
LANG:C++
DATE:2014-1-27
TASK:BitTree&SegTree
****************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define MAXN 50000
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rrep(i,a,b) for(int i=a;i>=b;--i)
#define lowbit(x) ((x)&(-(x)))
#define Mid (Left+Right>>1)
#define ls T->lc,loc,Left,Mid,ad
#define rs T->rc,loc,Mid+1,Right,ad
#define p_b push_back
#define sz(x) x.size()
struct Tree{
Tree* lc;
Tree* rc;
int sz;
};
Tree Pool[MAXN*400];
Tree* New=Pool;
Tree* null;
Tree* root[MAXN+10];
int N,Q;
int A[MAXN+10];
vector <Tree*> Plus;
vector <Tree*> Sub;
void _read(int& x){
char tt=getchar();
while(tt<'0'||'9'<tt) tt=getchar();
for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
}
void _read(char& x){
for(x=getchar();x!='Q'&&x!='C';x=getchar());
}
Tree* Get(Tree* lc,int sz,Tree* rc){
New->lc=lc;
New->sz=sz;
New->rc=rc;
return New++;
}
Tree* Modify(Tree* T,int loc,int Left,int Right,int ad){
if(Left==Right) return Get(null,T->sz+ad,null);
if(loc<=Mid) return Get(Modify(ls),T->sz+ad,T->rc);
if(loc>=Mid+1) return Get(T->lc,T->sz+ad,Modify(rs));
}
int Search(int k,int Left,int Right){
if(Left==Right) return Left;
int tmp=0,n=sz(Plus),m=sz(Sub);
n--;m--;
rep(i,0,n) tmp+=Plus[i]->lc->sz;
rep(i,0,m) tmp-=Sub[i]->lc->sz;
if(k<=tmp){
rep(i,0,n) Plus[i]=Plus[i]->lc;
rep(i,0,m) Sub[i]=Sub[i]->lc;
return Search(k,Left,Mid);
}
else{
rep(i,0,n) Plus[i]=Plus[i]->rc;
rep(i,0,m) Sub[i]=Sub[i]->rc;
return Search(k-tmp,Mid+1,Right);
}
}
void _init(){
_read(N);_read(Q);
rep(i,1,N) root[i]=null;
rep(i,1,N){
_read(A[i]);
for(int j=i;j<=N;j+=lowbit(j))
root[j]=Modify(root[j],A[i],1,MAXN,1);
}
}
void _solve(){
char Commend;
int l,r,k,t;
while(Q--){
_read(Commend);
if(Commend=='Q'){
_read(l);_read(r);_read(k);
Plus.clear();
Sub.clear();
for(int i=r;i;i-=lowbit(i)) Plus.p_b(root[i]);
for(int i=l-1;i;i-=lowbit(i)) Sub.p_b(root[i]);
printf("%d\n",Search(k,1,MAXN));
}
else{
_read(k);_read(t);
for(int i=k;i<=N;i+=lowbit(i)){
root[i]=Modify(root[i],A[k],1,MAXN,-1);
root[i]=Modify(root[i],t,1,MAXN,1);
}
A[k]=t;
}
}
}
int main(){
null=Get(0,0,0);
null->lc=null;
null->rc=null;
_init();
_solve();
return 0;
}
法二:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <deque>
#include <utility>
#include <functional>
#include <vector>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(int i=(b);i>=(a);--i)
#define lowbit(x) ((x)&(-(x)))
#define p_b push_back
#define MAXN 50000
int N,M;
int A[MAXN+10];
struct TrieNode{
TrieNode* ch[2];
int sz;
};
TrieNode Pool[MAXN*400];
TrieNode* New=Pool;
TrieNode* root[MAXN+10];
TrieNode* Get(TrieNode* lc,int sz,TrieNode* rc){
New->ch[0]=lc;
New->sz=sz;
New->ch[1]=rc;
return New++;
}
void _read(int& x){
char tt=getchar();
while(tt<'0'||'9'<tt) tt=getchar();
for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
}
void _read(char& x){
x=getchar();
while(x!='Q'&&x!='C') x=getchar();
}
void Insert(TrieNode* T,int key){
rrep(i,15,0){
T->sz++;
int t=(key>>i)&1;
if(!T->ch[t]) T->ch[t]=Get(0,0,0);
T=T->ch[t];
}
T->sz++;
}
void Delete(TrieNode* T,int key){
rrep(i,15,0){
T->sz--;
int t=(key>>i)&1;
T=T->ch[t];
}
T->sz--;
}
void _init(){
_read(N);
_read(M);
rep(i,1,N) root[i]=Get(0,0,0);
rep(i,1,N){
_read(A[i]);
for(int j=i;j<=N;j+=lowbit(j))
Insert(root[j],A[i]);
}
}
int Select(){
vector <TrieNode*> Plus;
vector <TrieNode*> Sub;
int l,r,k,n,m;
_read(l);
_read(r);
_read(k);
for(int j=r;j;j-=lowbit(j)) Plus.p_b(root[j]);
for(int j=l-1;j;j-=lowbit(j)) Sub.p_b(root[j]);
n=Plus.size();
m=Sub.size();
int rt=0;
rrep(i,15,0){
int t=0;
rep(j,0,n-1) if(Plus[j]&&Plus[j]->ch[0]) t+=Plus[j]->ch[0]->sz;
rep(j,0,m-1) if(Sub[j]&&Sub[j]->ch[0]) t-=Sub[j]->ch[0]->sz;
if(k<=t){
rep(j,0,n-1) if(Plus[j]) Plus[j]=Plus[j]->ch[0];
rep(j,0,m-1) if(Sub[j]) Sub[j]=Sub[j]->ch[0];
}
else{
k-=t;
rt+=(1<<i);
rep(j,0,n-1) if(Plus[j]) Plus[j]=Plus[j]->ch[1];
rep(j,0,m-1) if(Sub[j]) Sub[j]=Sub[j]->ch[1];
}
}
return rt;
}
void Modify(){
int k,t;
_read(k);
_read(t);
for(int j=k;j<=N;j+=lowbit(j)){
Delete(root[j],A[k]);
Insert(root[j],t);
}
A[k]=t;
}
void _solve(){
char T;
while(M--){
_read(T);
if(T=='Q') printf("%d\n",Select());
else Modify();
}
}
int main(){
_init();
_solve();
return 0;
}