动态区间k小问题

【题目地址】点击打开链接


【分析】

法一:

        其实就是在静态区间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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值