F. Range Update Point Query

题目:

 给一个n个数的数组,q次询问,如果是1,更新l~r的值,如果是二,输出a[x]的值。本来思路是暴力,对于每个a[i]调用一个sum函数更新,结果一直超时。题解思路是:对于一个很大的数,最多三次就会更新为一个10以内的数,比如999999999,一次更新为81,二次为9,之后不再更新,所以题解没有对a[i]<9的数进行更新操作了,并且用set容器记录了值大于9的数组的下标,对l~r的数组操作时,只操作数组值大于9的下标。

代码:

    cin>>t;
	while (t--)
	{
		
		scanf("%d%d",&n,&q);
		vector <long long > a(n+1);//数组a,从一开始,所以开n+1个
		set<int> s;记录下标的数组;
		for (int i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
			if (a[i]>9)
			s.insert(i);//存入下标
		}
		while (q--)
		{
			
			scanf("%d",&m);
			if (m==1)			
			{
				scanf("%d%d",&l,&r);
				int num=l;
				while (!s.empty())//当有下标数组不为空是进行循环
				{
					
					auto x=s.lower_bound(num);//二分找到下标大于等于num的迭代器
					if (x==s.end()||*x>r)//如果没有找到或者超出范围跳出循环
					break;
					a[*x]=sum(a[*x]);//更新数组
					int p=*x;
					s.erase(x);//删除x
					if (a[p]>9)s.insert(p);//重新判断一下
					num=p+1;//移向下一个
				}
			}
			else {
				scanf("%d",&l);
				cout<<a[l]<<endl;
			}
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值