1. 程式人生 > >[洛谷P2801]教主的魔法

[洛谷P2801]教主的魔法

大於 時間復雜度 tchar har 個數 數列 ems 重新 題目

題目大意:有n個數,q個操作。操作有兩種:①把一段區間所有數加上p;②查詢一段區間內大於等於p的元素的個數。

解題思路:詢問次數少,可以用分塊解決。

將所有數分成$\sqrt{n}$塊,對每一塊進行排序。

用a數組存原來的數列,b數組存排完序後的數列。

查詢時,對左右兩個塊中的數據暴力查詢,中間的由於整塊訪問並排完序,直接二分查找即可。

修改數據時,對左右兩個塊中的數據暴力修改,並且更新b數組(重新排序),對中間的,由於相對大小不變,直接打上標記即可。

修改時,最多對兩個塊進行排序,時間復雜度$O(\sqrt{n}\log_2\sqrt{n})$。

查詢時,最多對所有塊都進行二分查找,時間復雜度$O(\sqrt{n}\log_2\sqrt{n})$。

故總時間復雜度$O(q\sqrt{n}\log_2\sqrt{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\n",ans);
		}
	}
	return 0;
}

[洛谷P2801]教主的魔法