ZYXzyx123

 

XCSY暑期集训模拟赛2T3善良

暴力(50pts)

对于每个询问,遍历\([l,r]\),统计其中k的数量,时间复杂度为\(O(nm)\)

for(int i=1;i<=n;i++)	cin>>a[i];
while(m--){
	cin>>l>>r>>k;
	int ans=0;
	for(int i=l;i<=r;i++){
		if(a[i]==k)	ans++;
	}
	cout<<ans<<'\n';
}

二分(100pts)

\(map[i]\)统计数字\(i\)出现的所有位置,每个\(map[i](1 \leq i \leq n)\)都是单调递增的。

对于每个询问,在\(map[k]\)中二分找到第一个\(\geq l\)和最后一个\(\leq r\)的数的位置,计算其中共包含多少个数即可(包含左右端点,具体见代码)

map<int,vector<int> >mp;//mp[i]表示数字i出现的所有位置
for(int i=1;i<=n;i++){
	cin>>a;
	mp[a].push_back(i);
}
while(m--){
	cin>>l>>r>>k;
	vector<int>v=mp[k];
	if(v.empty()||v[0]>r||v[v.size()-1]<l){//没有符合要求的数
		cout<<0<<'\n';
		continue;
	}
	int left=0,right=v.size()-1;
	while(left<right){
		int mid=left+right>>1;
		if(v[mid]<l)	left=mid+1;
		else	right=mid;
	}
	int x=right;//找第一个≥l的数的位置
	if(v[v.size()-1]<=r){//所有x以后的数均≤r,最后一个≤r的数的位置就是最后一个位置
		cout<<v.size()-x<<'\n';//左端点为x,右端点为v.size()-1,共有v.size()-1-x+1=v.size()-x个数
	}else{
		left=right,right=v.size()-1;
		while(left<right){
			int mid=left+right>>1;
			if(v[mid]>r)	right=mid;
			else	left=mid+1;
		}//找第一个>r的数的位置,减1就是最后一个≤r的数的位置
		cout<<left-x<<'\n';//左端点为x,右端点为left-1,共有left-1-x+1=left-x个数
	}
}

posted on 2025-10-03 19:47  ZYXzyx123  阅读(8)  评论(0)    收藏  举报

导航