教主的魔法

题目描述
教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。

每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)

CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。

WD巨懒,于是他把这个回答的任务交给了你。

输入格式
第1行为两个整数N、Q。Q为问题数与教主的施法数总和。

第2行有N个正整数,第i个数代表第i个英雄的身高。

第3到第Q+2行每行有一个操作:

(1). 若第一个字母为“M”,则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。
(2). 若第一个字母为“A”,则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。
输出格式
对每个“A”询问输出一行,仅含一个整数,表示闭区间 [L, R] 内身高大于等于C的英雄数。

样例
样例输入
5 3
1 2 3 4 5
A 1 5 4
M 3 5 1
A 1 5 4
样例输出
2
3

我也懒,所以直接把题面粘过来了
我当时一看这玩意,这不纯纯板子吗,然后就去打了,然后…………
image
大唐盛世…………
第一个错点,忘分块了
分完块,就T了
后面问了wlesq,说是二分,实际上T了之后也想过二分,但但想的是查询的时候,排一遍序,再用二分(那还不如直接遍历)
然后就卡住了,后面瞟了一眼题解,看了个大概,好像是再修改和分块的时候,排序,且只用给散块排序(因为整块同加同减,不会变顺序),然后就开搞了
然后就又卡在一个问题上,排完序后数不对应,且没啥好方法,所以索性就这么搞了

struct node{
	int num;
	int id;
}a[1200000];
bool cmp1(const node&a,const node&b){
	return a.num<b.num;
}
bool cmp2(const node&a,const node&b){
	return a.id<b.id;
}

sort(a+l[p],a+1+r[p],cmp2);
for(int i=x;i<=y;i++){
	a[i].num+=z;
}
sort(a+l[p],a+1+r[p],cmp1);

先按序号将数排回来,修改完后排回去,就可以解决了
后面就没什么大问题了

唐氏错误
1.演员二分

while(le<=ri){
	int mid=(le+ri)/2;
	if(a[mid].num+lazy[i]<=z){
	le=mid+1;ans1=r[i]-mid+1;
	}
	else{
	ri=mid-1;
	}
}//错的
while(le<=ri){
	int mid=(le+ri)/2;
	if(a[mid].num+lazy[i]<z){
	le=mid+1;
	}
	else{
	ri=mid-1;ans1=r[i]-mid+1;
	}
}//正确的

2.数组开小(少开了1)
image
3.查询时排序
image
还有就是排序的时候是
sort(a+l[q],a+1+r[q]);
而不是
sort(a+l[q]+1,a+1+r[q]);
可以类比于
sort(a+1,a+1+n);
会发现,左边界是1,右边界是n

fixed:今天Elaina_0查题解时发现hack代码,然后我去试了试,然后寄了,后面发现,再修改时并未将区间内数组按编号排回去,导致查询出锅,再查询前加上按编号排序就好了(查完不用归位,修改时就自动排了)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int lazy[1200000];
int l[1200000],r[1200000];
int vis[1200000];
struct node{
	int num;
	int id;
}a[1200000];
bool cmp1(const node&a,const node&b){
	return a.num<b.num;
}
bool cmp2(const node&a,const node&b){
	return a.id<b.id;
}
int n,m;
void div(){
	int sq=sqrt(n);
	for(int i=1;i<=sq;i++){
		l[i]=(i-1)*sq+1;
		r[i]=sq*i;
	}
	if(r[sq]<n){
		sq++;
		l[sq]=r[sq-1]+1;
		r[sq]=n;
	}
	for(int i=1;i<=sq;i++){
		sort(a+l[i],a+r[i]+1,cmp1);
		for(int j=l[i];j<=r[i];j++){
			vis[j]=i;
		}
	}
}
void add(int x,int y,int z){
	int p=vis[x],q=vis[y];
	if(p==q){
		sort(a+l[p],a+1+r[p],cmp2);
		for(int i=x;i<=y;i++){
			a[i].num+=z;
		}
		sort(a+l[p],a+1+r[p],cmp1);
	}
	else {
		sort(a+l[p],a+1+r[p],cmp2);
		for(int i=x;i<=r[p];i++){
			a[i].num+=z;
		}
		sort(a+l[p],a+1+r[p],cmp1);
		for(int i=p+1;i<q;i++){
			lazy[i]+=z;
		}
		sort(a+l[q],a+1+r[q],cmp2);
		for(int i=l[q];i<=y;i++){
			a[i].num+=z;
		}
		sort(a+l[q],a+1+r[q],cmp1);
	}
}
int query(int x,int y,int z){
	int ans=0;
	int p=vis[x],q=vis[y];
	if(p==q){
		sort(a+l[q],a+1+r[q],cmp2);
		for(int i=x;i<=y;i++){
			if(a[i].num+lazy[p]>=z) ans++;
		}
//		sort(a+l[q],a+1+r[q],cmp1);
	}
	else {
		sort(a+l[p],a+1+r[p],cmp2);
		for(int i=x;i<=r[p];i++){
			if(a[i].num+lazy[p]>=z) ans++;
		}
//		sort(a+l[p],a+1+r[p],cmp1);
		int ans1=0;
		for(int i=p+1;i<q;i++){
			int le=l[i],ri=r[i];
			while(le<=ri){
				int mid=(le+ri)/2;
				if(a[mid].num+lazy[i]<z){
					le=mid+1;
				}
				else{
					ri=mid-1;ans1=r[i]-mid+1;
				}
			}
			ans+=ans1;ans1=0;
		}
		sort(a+l[q],a+1+r[q],cmp2);
		for(int i=l[q];i<=y;i++){
			if(a[i].num+lazy[q]>=z) ans++;
		}
//		sort(a+l[q],a+1+r[q],cmp1);
	}
	return ans;
}
int main(){
	int x,y,z;
	string s;
	cin>>n>>m;
	for(int i=1;i<=n;i++) {cin>>a[i].num;a[i].id=i;}
	div();
	for(int i=1;i<=m;i++){
		cin>>s;
		if(s=="M"){
			cin>>x>>y>>z;
			add(x,y,z);
		}
		else {
			cin>>x>>y>>z;
			cout<<query(x,y,z)<<endl;
		}
	}
}
/*
10 5
39 56 58 26 89 11 86 31 84 21
M 6 8 80
M 1 2 90
A 1 1 88
*/
posted @ 2024-04-19 15:44  shaoyufei  阅读(20)  评论(0编辑  收藏  举报