• [洛谷P2801]教主的魔法


    题目大意:有n个数,q个操作。操作有两种:①把一段区间所有数加上p;②查询一段区间内大于等于p的元素的个数。

    解题思路:询问次数少,可以用分块解决。

    将所有数分成$sqrt{n}$块,对每一块进行排序。

    用a数组存原来的数列,b数组存排完序后的数列。

    查询时,对左右两个块中的数据暴力查询,中间的由于整块访问并排完序,直接二分查找即可。

    修改数据时,对左右两个块中的数据暴力修改,并且更新b数组(重新排序),对中间的,由于相对大小不变,直接打上标记即可。

    修改时,最多对两个块进行排序,时间复杂度$O(sqrt{n}log_2sqrt{n})$。

    查询时,最多对所有块都进行二分查找,时间复杂度$O(sqrt{n}log_2sqrt{n})$。

    故总时间复杂度$O(qsqrt{n}log_2sqrt{n})$。

    C++ Code:

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cctype>
    using namespace std;
    int a[1000005],b[1000005];
    int n,q,size,l[1005],r[1005],blocks,add[1005],inbk[1000005];
    char s[4];
    inline int readint(){
        char c=getchar();
        for(;!isdigit(c);c=getchar());
        int d=0;
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
        return d;
    }
    void chan(int blk){
    	for(int i=l[blk];i<=r[blk];++i)
    	b[i]=a[i];
    	sort(b+l[blk],b+r[blk]+1);
    }
    int main(){
    	n=readint();q=readint();
    	size=(int)(sqrt(n)+0.00000001);
    	blocks=0;
    	l[1]=1;
    	for(int i=1;i<=n;++i){
    		a[i]=b[i]=readint();
    		inbk[i]=blocks+1;
    		if(i%size==0){
    			r[++blocks]=i;
    			l[blocks+1]=i+1;
    		}
    	}
    	if(n%size)
    	r[++blocks]=n;
    	for(int i=1;i<=blocks;++i)
    	sort(b+l[i],b+r[i]+1);
    	memset(add,0,sizeof add);
    	while(q--){
    		scanf("%s",s);
    		if(s[0]=='M'){
    			int L=readint(),R=readint(),p=readint();
    			if(L>R)L^=R^=L^=R;
    			int lft=inbk[L],rgt=inbk[R];
    			if(lft==rgt){
    				for(int i=L;i<=R;++i)a[i]+=p;
    				chan(lft);
    			}else{
    				for(int i=lft+1;i<rgt;++i)add[i]+=p;
    				for(int i=L;i<=r[lft];++i)a[i]+=p;
    				for(int i=l[rgt];i<=R;++i)a[i]+=p;
    				chan(lft);
    				chan(rgt);
    			}
    		}else{
    			int L=readint(),R=readint(),p=readint(),ans=0;
    			int lft=inbk[L],rgt=inbk[R];
    			if(lft==rgt){
    				for(int i=L;i<=R;++i)
    				if(a[i]+add[lft]>=p)++ans;
    			}else{
    				for(int i=lft+1;i<rgt;++i)
    				ans+=r[i]-(lower_bound(b+l[i],b+r[i]+1,p-add[i])-b-1);
    				for(int i=L;i<=r[lft];++i)
    				if(a[i]+add[lft]>=p)++ans;
    				for(int i=l[rgt];i<=R;++i)
    				if(a[i]+add[rgt]>=p)++ans;
    			}
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    iscsi一致性的测试验证方法
    ceph各个版本之间参数变化分析
    rgw的rgw_thread_pool_size配置调整
    rgw前端替换civetweb为beast
    配置内网访问的TV
    关于vm.min_free_kbytes的合理设置推测
    rbd的删除回收站功能
    python爬取微博热门话题榜
    Selenium+Pytest自动化测试框架—禅道实战
    python带参数装饰器的两种写法
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7742626.html
Copyright © 2020-2023  润新知