2021辽宁省赛 I 完美主义 树状数组/暴力

Remember, Red, hope is good thing, mabye the best of things. And no good thing ever die.——肖申克的救赎


题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述
阿强采摘了一些苹果,并把他们分堆排成了一行,从左往右编号为第 1 … 𝑛 堆,其中第𝑖堆苹果有 a i a_i ai个。
完美主义者阿珍看到这些苹果,觉得他们摆放的非常杂乱。她要求阿强进行如下的操作。
对某堆苹果进行调整:阿强将会将第𝑖堆苹果调整成 b i b_i bi个;
对阿珍询问做出答复:其中每次询问表示为[𝑙, 𝑟],表示询问第𝑙堆到第𝑟堆之间的苹果数量是否满足 a l ≤ a l + 1 ≤ … ≤ a r − 1 ≤ a r a_l\le a_{l+1} \le …\le a_{r-1} \le a_r alal+1ar1ar,如果满足则称为完美。

输入描述
第一行两个整数n,q(1<=n,q<=3*10^5),表示苹果的堆数和操作的个数;
第二行n个整数表示 a i a_i ai
以下𝑞行,每行3个整数,第一个整数为opt;
若opt = 1,之后两个整数 i , b i i,b_i i,bi表示将第𝑖堆苹果调整为 b i b_i bi个;
若opt = 2,之后两个整数𝑙, 𝑟,表示对[𝑙, 𝑟]之间的苹果堆进行询问。(1<= a i , b i a_i,b_i ai,bi<=10^9)

输出描述:
输出一共𝑞行,每行一个 Yes 或者 No,表示每个询问对应区间是否完美。

输入
7 4
1 2 2 4 3 4 5
1 1 4
2 1 7
2 6 7
2 4 7
输出
No
Yes
No

队友A的想法:
先把这些数用a数组存起来,然后再用一个树状数组c表示每一个数对于前一个数是不是非递减,如果这个数大于等于前面的数,就记为0,否则记为-1。

1224345
0000-100

这样我们可以用树状数组实现logn的修改和查询,如果l到r是完美区间,则sum(r )-sum(l+1)=0。
但是因为我太菜了,一直WA…
然后队友B突然说这题过了,我们都很震惊,发现居然暴力就能过:D。。。。。
晚上回来终于把这题改过了,说明这个思路是没问题的
树状数组版

#include<bits/stdc++.h>
using namespace std;
long long c[300005];
long long num[300005];
int n;
int lowbit(int x){
	return (x&(-x));
}
void update(int i,int val){
	 while(i<=n){
	 	c[i]+=val;
	 	i+=lowbit(i);
	 }
}
int sum(long long i){
	int ans=0;
	while(i>=1){
		ans+=c[i];
		i-=lowbit(i);
	}
	return ans;
}
int main(){
	int q,i;
	cin>>n>>q;
	for(i=1;i<=n;i++){
	    cin>>num[i];
		if(num[i]<num[i-1]){//如果一个数小于前一个数,就把它设为-1
			update(i,-1);
		}
	}
	for(i=1;i<=q;i++){
		int opt;
		long long a,b;
		cin>>opt>>a>>b;
		if(opt==1){
			num[a]=b;
			//更改一个数,要判断这个数和后面那个数!
		    if(b>=num[a-1]) {//这个数大于等于前一个数
		    	if(sum(a)-sum(a-1)==-1) update(a,1);
		    	//如果这个数原本小于前面的数,将-1改为0;如果这个数原本大于等于前面的数就不用改
			}
			else{//这个数小于前一个数
			if(sum(a)-sum(a-1)==0) update(a,-1);
			//如果这个数原本大于等于前面的数,将0改为-1,;如果这个数原本小于前面的数就不用改
			}
			if(num[a+1]>=b){//判断这个数的后一个数,同上。
				if(sum(a+1)-sum(a)==-1) update(a+1,1);
			}
			else{
				if(sum(a+1)-sum(a)==0) update(a+1,-1);
			}
			
		}
		else if(opt==2){
			int ans=sum(b)-sum(a);//计算a+1到b的区间和
			if(ans==0) cout<<"Yes"<<endl;
			else cout<<"No"<<endl;
		}
}
	return 0;
}

暴力版

#include<iostream>
using namespace std;
int main(){
	int n,q,l,r,opt;
	long long a[300005];
	cin>>n>>q;
	int i,j;
	for(i=1;i<=n;i++){
		cin>>a[i];
	}
	for(i=1;i<=q;i++){
		cin>>opt>>l>>r;
		if(opt==1)a[l]=r;
		
		else{
			for(j=l;j<r;j++){
				if(a[j]>a[j+1])break;
			}
			if(j==r)cout<<"Yes"<<endl;
			else cout<<"No"<<endl;
		}//cout<<a[l]<<" ";
	}
	return 0;
}

这道题告诉我们如果实在不会要勇敢的写暴力!!说不定就过了!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值