• LUOGU P2617 Dynamic Rankings(树状数组套主席树)


    传送门

    解题思路

      动态区间第(k)大,树状数组套主席树模板。树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和。然后询问的时候(log)个点一起做前缀和,一起移动。时空复杂度(O(nlog^2n))

    代码

    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    
    using namespace std;
    const int N=100005;
    const int M=200005*18*18;
    
    inline int rd(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f?x:-x;	
    }
    
    int n,m,tmp[25][2],a[N],cpy[N<<1],u,cnt,rt[N];
    int cnt0,cnt1;
    struct Segment_tree{
    	int ls,rs,w;	
    }t[M];
    struct Ask{
    	int op,l,r,k;	
    }q[N];
    
    void update(int &x,int l,int r,int pos,int val){
    	if(!x) x=++cnt;t[x].w+=val;
    	if(l==r) return ;int mid=(l+r)>>1;
    	if(pos<=mid) update(t[x].ls,l,mid,pos,val);
    	else update(t[x].rs,mid+1,r,pos,val);
    }	
    
    inline void prepare_update(int x,int val){
    	int now=lower_bound(cpy+1,cpy+1+u,a[x])-cpy;
    	for(int i=x;i<=n;i+=i&-i) update(rt[i],1,u,now,val);
    }
    
    int query(int l,int r,int k){
    	if(l==r) return l;int sum=0,mid=(l+r)>>1;
    	for(int i=1;i<=cnt1;i++) sum+=t[t[tmp[i][1]].ls].w;
    	for(int i=1;i<=cnt0;i++) sum-=t[t[tmp[i][0]].ls].w;
    	if(sum>=k){
    		for(int i=1;i<=cnt0;i++) tmp[i][0]=t[tmp[i][0]].ls;
    		for(int i=1;i<=cnt1;i++) tmp[i][1]=t[tmp[i][1]].ls;
    		return query(l,mid,k);
    	}	
    	else {
    		for(int i=1;i<=cnt0;i++) tmp[i][0]=t[tmp[i][0]].rs;
    		for(int i=1;i<=cnt1;i++) tmp[i][1]=t[tmp[i][1]].rs;
    		return query(mid+1,r,k-sum);
    	}
    }	
    
    inline int prepare_query(int l,int r,int k){
    	memset(tmp,0,sizeof(tmp));cnt0=cnt1=0;
    	for(int i=l-1;i;i-=i&-i) tmp[++cnt0][0]=rt[i];
    	for(int i=r;i;i-=i&-i) tmp[++cnt1][1]=rt[i];
    	return query(1,u,k);
    }	
    
    int main(){
    	n=rd(),m=rd();char c;int num=n;
    	for(int i=1;i<=n;i++) cpy[i]=a[i]=rd();
    	for(int i=1;i<=m;i++) {
    		c=' ';while(c!='Q' && c!='C') c=getchar();
    		if(c=='C') q[i].op=1,q[i].l=rd(),q[i].k=rd(),cpy[++num]=q[i].k;
    		else q[i].op=2,q[i].l=rd(),q[i].r=rd(),q[i].k=rd(); 
    	}
    	sort(cpy+1,cpy+1+num);
    	u=unique(cpy+1,cpy+1+num)-cpy-1;
    	for(int i=1;i<=n;i++) prepare_update(i,1);
    	for(int i=1;i<=m;i++){
    		if(q[i].op==1){
    			prepare_update(q[i].l,-1);
    			a[q[i].l]=q[i].k;
    			prepare_update(q[i].l,1);
    		}
    		else printf("%d
    ",cpy[prepare_query(q[i].l,q[i].r,q[i].k)]);	
    	}	
    	return 0;	
    }
    
    
  • 相关阅读:
    IO流总览图
    自己实现的一个数组排序并去重的功能
    Java常量池详解之一道比较蛋疼的面试题
    一个简单的数组去重并排序方法
    Delphi开发经验谈
    再谈Delphi vs VC++(非常精彩)
    C#根据当前时间获取,本周,本月,本季度等时间段
    delphi CopyMemory、FillMemory、MoveMemory、ZeroMemory
    DupeString 与 StringOfChar 的区别
    SQL最大值加1
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10230889.html
Copyright © 2020-2023  润新知