zoukankan      html  css  js  c++  java
  • 整体二分学习笔记

    用途

    在信息学竞赛中,有一部分题可以使用二分的办法来解决。

    但是当这种题目有多次询问且每次询问我们对每个查询都直接二分,可能会收获一个 (TLE)

    这时候我们就会用到整体二分。

    整体二分的主体思路就是把多个查询一起解决。(所以这是一个离线算法)

    可以使用整体二分解决的题目需要满足以下性质:

    (1)、询问的答案具有可二分性

    (2)、修改对判定答案的贡献互相独立,修改之间互不影响效果

    (3)、修改如果对判定答案有贡献,则贡献为一确定的与判定标准无关的值

    (4)、贡献满足交换律,结合律,具有可加性

    (5)、题目允许使用离线算法

    实现

    P3332 [ZJOI2013]K大数查询 为例

    暴力的做法就是二分一个权值,查看大于等于这个权值的数是不是大于等于 (k) 个。

    如果是,就把这个权值增大,否则就去缩小这个权值。

    整体二分需要实现一个函数 (solve(al,ar,bl,br))

    表示对于当前询问的区间 ([al,ar]),二分的权值在 ([bl,br]) 范围中。

    (mids=(bl+br)/2),我们去遍历 ([al,ar]) 中的所有操作。

    如果是修改操作并且加入的权值在 ([mids+1,br]) 中,把对应的区间 ([l,r])整体加一。

    如果是询问操作,去查询 ([l,r]) 中有多少数,如果有大于等于 (k) 个,我们就把这个询问放到递归的右区间中,否则就放到左区间中。

    当二分权值的左右端点相等时就去更新答案。

    最后不要忘了把加入的贡献清除。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #define rg register
    template<typename T>void read(T &x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=2e5+5;
    struct trr{
    	int l,r,laz,siz;
    	long long sum;
    }tr[maxn];
    void push_up(rg int da){
    	tr[da].sum=tr[da<<1].sum+tr[da<<1|1].sum;
    }
    void push_down(rg int da){
    	if(!tr[da].laz) return;
    	tr[da<<1].laz+=tr[da].laz;
    	tr[da<<1|1].laz+=tr[da].laz;
    	tr[da<<1].sum+=1LL*tr[da<<1].siz*tr[da].laz;
    	tr[da<<1|1].sum+=1LL*tr[da<<1|1].siz*tr[da].laz;
    	tr[da].laz=0;
    }
    void build(rg int da,rg int l,rg int r){
    	tr[da].l=l,tr[da].r=r,tr[da].siz=r-l+1;
    	if(l==r) return;
    	rg int mids=(l+r)>>1;
    	build(da<<1,l,mids),build(da<<1|1,mids+1,r);
    }
    void xg(rg int da,rg int l,rg int r,rg int val){
    	if(tr[da].l>=l && tr[da].r<=r){
    		tr[da].laz+=val;
    		tr[da].sum+=tr[da].siz*val;
    		return;
    	}
    	push_down(da);
    	rg int mids=(tr[da].l+tr[da].r)>>1;
    	if(l<=mids) xg(da<<1,l,r,val);
    	if(r>mids) xg(da<<1|1,l,r,val);
    	push_up(da);
    }
    long long cx(rg int da,rg int l,rg int r){
    	if(tr[da].l>=l && tr[da].r<=r) return tr[da].sum;
    	push_down(da);
    	rg int mids=(tr[da].l+tr[da].r)>>1;
    	rg long long nans=0;
    	if(l<=mids) nans+=cx(da<<1,l,r);
    	if(r>mids) nans+=cx(da<<1|1,l,r);
    	return nans;
    }
    int n,m,ans[maxn],id[maxn];
    struct asd{
    	int op,l,r;
    	long long val;
    	asd(){}
    	asd(rg int aa,rg int bb,rg int cc,rg long long dd){
    		op=aa,l=bb,r=cc,val=dd;
    	}
    }b[maxn];
    int tmp1[maxn],tmp2[maxn];
    void solve(rg int al,rg int ar,rg int bl,rg int br){
    	if(bl==br){
    		for(rg int i=al;i<=ar;i++) ans[id[i]]=bl;
    		return;
    	}
    	rg int mids=(bl+br)>>1,now1=0,now2=0;
    	for(rg int i=al;i<=ar;i++){
    		if(b[id[i]].op==1){
    			if(b[id[i]].val>mids){
    				tmp2[++now2]=id[i];
    				xg(1,b[id[i]].l,b[id[i]].r,1);
    			} else {
    				tmp1[++now1]=id[i];
    			}
    		} else {
    			rg long long tmp=cx(1,b[id[i]].l,b[id[i]].r);
    			if(b[id[i]].val<=tmp){
    				tmp2[++now2]=id[i];
    			} else {
    				b[id[i]].val-=tmp;
    				tmp1[++now1]=id[i];
    			}
    		}
    	}
    	for(rg int i=al;i<=ar;i++){
    		if(b[id[i]].op==1){
    			if(b[id[i]].val>mids){
    				xg(1,b[id[i]].l,b[id[i]].r,-1);
    			} 
    		}
    	}
    	for(rg int i=1;i<=now1;i++) id[al+i-1]=tmp1[i];
    	for(rg int i=1;i<=now2;i++) id[al+now1+i-1]=tmp2[i];
    	solve(al,al+now1-1,bl,mids);
    	solve(al+now1,ar,mids+1,br);
    }
    int main(){
    	read(n),read(m);
    	rg int aa,bb,cc;
    	rg long long dd;
    	for(rg int i=1;i<=m;i++){
    		read(aa),read(bb),read(cc),read(dd);
    		b[i]=asd(aa,bb,cc,dd);
    	}
    	for(rg int i=1;i<=m;i++) id[i]=i;
    	build(1,1,n);
    	solve(1,m,-n,n);
    	for(rg int i=1;i<=m;i++){
    		if(b[i].op==2) printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    架构 框架 设计模式 --备用
    机器视觉项目开发之---织物疵点检测机器视觉系统 软件测试平台
    多媒体开发之--- live555 vs2010/vs2013下编译,使用,测试
    多媒体开发之--- h264 图像、帧、片、NALU
    多媒体开发之---H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
    多媒体开发之---h264格式slice_header
    图像处理之基础---傅立叶c实现
    图像处理之基础---小波提取特征
    图像处理之基础---图像的特征简介
    嵌入式开发之工具---log file
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/14526377.html
Copyright © 2011-2022 走看看