zoukankan      html  css  js  c++  java
  • 整体二分

    A. 求区间第 (k) 大数

    整体二分的思想其实和cdq分治有一点相似之处。
    具体操作:

    def q[],q1[],q2[],cnt1,cnt2
    
    solve(l,r,val_l,val_r){
    
    if val_l==val_r
        将所有[l,r]中的q中的询问答案设为val_l,return
    
    for i in [l,r]
        if q[i]是修改操作
            更新树状数组 位置:q[i].pos 值:q[i].val
            q1[++cnt1]=q[i]
        else
            q2[++cnt2]=q[i]
    
    将树状数组中所有操作撤销
    将q1,q2中的操作复制到q中
    设mid=(val_l+val_r)/2
    solve(l,l+cnt1-1,val_l,mid)
    solve(l+cnt1,r,mid+1,val_r)
    
    }
    

    Code

    #include<cstdio>
    #include<algorithm>
    #define maxn 200003
    #define INF 1050000000
    using namespace std;
    struct T{
    	int mo,l,r,k,num;
    	T(){}
    	T(int _mo,int _l,int _r,int _k,int _num):mo(_mo),l(_l),r(_r),k(_k),num(_num){}
    }q[maxn],ql[maxn],qr[maxn];
    int t[maxn],n,m,ANS[maxn];
    void add(int pos,int k){while(pos<=n)t[pos]+=k,pos+=pos&-pos;}
    int query(int pos){int ret=0;while(pos)ret+=t[pos],pos-=pos&-pos;return ret;}
    void bin(int l,int r,int val_l,int val_r){
    	if(l>r)return;
    	if(val_l==val_r){
    		for(int i=l;i<=r;i++){
    			if(q[i].mo==2)ANS[q[i].num]=val_l;
    		}
    		return;
    	}
    	int cntl=0,cntr=0,val_mid=(val_l+val_r)>>1;
    	for(int i=l;i<=r;i++){
    		if(q[i].mo==1){
    			if(q[i].k<=val_mid){
    				add(q[i].num,1);
    				ql[++cntl]=q[i];
    			}
    			else{
    				qr[++cntr]=q[i];
    			}
    		}
    		else{
    			int tmp=query(q[i].r)-query(q[i].l-1);
    			if(q[i].k<=tmp){
    				ql[++cntl]=q[i];
    			}
    			else{
    				q[i].k-=tmp;
    				qr[++cntr]=q[i];
    			}
    		}
    	}
    	for(int i=1;i<=cntl;i++){
    		if(ql[i].mo==1)add(ql[i].num,-1);
    	}
    	for(int i=1;i<=cntl;i++){
    		q[l+i-1]=ql[i];
    	}
    	for(int i=1;i<=cntr;i++){
    		q[l+i+cntl-1]=qr[i];
    	}
    	bin(l,l+cntl-1,val_l,val_mid);
    	bin(l+cntl,r,val_mid+1,val_r);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		int a;
    		scanf("%d",&a);
    		q[i]=T(1,0,0,a,i);
    	}
    	for(int i=1;i<=m;i++){
    		int x,y,k;
    		scanf("%d%d%d",&x,&y,&k);
    		q[i+n]=T(2,x,y,k,i);
    	}
    	bin(1,n+m,-INF,INF);
    	for(int i=1;i<=m;i++)printf("%d
    ",ANS[i]);
    	return 0;
    }
    

    B. 区间 (k) 大数带修改

    一样的,把修改操作视为先删除再插入。

    C. 区间 (k) 大数带插入

    题意

    (N) 个桶,每次操作是将 ([l,r]) 中的每个桶加入一个树,求区间 (k) 大数。

    一样的,没有任何区别。

  • 相关阅读:
    scp命令报错-bash: scp: command not found
    shell比较两个字符串是否相等
    bat脚本:自动压缩n天前的文件【转载】
    shell bash判断文件或文件夹是否存在
    linux文件分割(将大的日志文件分割成小的)【转载】
    TCP/IP模型各个层次的功能和协议
    nginx初级安装配置
    Heartbeat+DRBD+MySQL高可用方案【转】
    【转载】CentOS 6.4下PXE+Kickstart无人值守安装操作系统
    oracle的exp和imp命令的使用【转载】
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/10547069.html
Copyright © 2011-2022 走看看