鸡格线(map操作)

鸡格线 (nowcoder.com)

题目描述
你有一个长为n的数组a,你需要支持以下两种操作:
1、输入l, r, k,对区间[1,r]中所有数字执行a;= f(a;)操作k次(式中等号表示赋值操作),之中f(z)=round(10、c),round为四舍五入函数。
2、输出当前数组所有数字的和。
你需要正确处理m次这样的操作。
输入描述:
输入第一行包含两个整数n, m(1 接下来一行输入n个整数,第i个整数a;(0≤ai≤10)表示数组第i个数。
接下来m行,每行先输入一个操作类别op(op ∈ {1,2}),表示两类操作之一,若op = 1,则继续输入三个整数l, r,k(1 ≤l≤r ≤n,1 ≤k≤105),含义如题目所示。
输出描述:
对于所有第二类操作,输出一个整数表示当前数组所有数字的和。
示例1
输入
复制
3 5
0 2 114514
2
1 1 2 2
2
1 1 3 1
2
输出
复制
114516
114551
3445

题解:

题意很容易理解,应该是线段树的板子题

关键是这一个操作,输入l, r, k,对区间[1,r]中所有数字执行a;= f(a;)操作k次(式中等号表示赋值操作),之中f(z)=round(10、c),round为四舍五入函数。

执行k次,好像k在1e5,普通写肯定是会t的,

有哪点没考虑到捏

就是这个

 我们发现如果一个数执行次数超出一个固定值后就不会再改变了,

这里介绍一种mapstl操作,非线段树,,写起来很方便(具体细节代码有注释)

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
using namespace std;
typedef pair PII;
const int N = 5e5 + 10;
int n,m;
void solve()
{
	cin >> n >> m;
	map f;
	int s = 0;
	for(int i = 1;i <= n;i++)
	{
		int x;
		cin >> x;
		s += x;
		f[i] = x;
	} 
	f[0] = -1,f[n+1] = -1;//要限制边界,否则会越界
	while(m--)
	{
		int op;
		cin >> op;
		if(op == 2)
		{
			cout << s<<'\n';
		}
		else
		{
			int l,r,k;
			cin >>l >> r >> k; 
			for(auto it = f.lower_bound(l);it ->first <= r;it ++)//每次找到地址it,it -> first为下标
			{
				int tk = k;
				while(tk--)
				{
					int tt = round(10*sqrtl(it -> second));//round和sqrtl都是stl自带函数
					s = s - it->second + tt;//修改总值
					it -> second = tt;//修改原来的值
					if(tt == 0||tt==99||tt==100)
					{
						it = f.erase(it);//如果执行后值达到某一个值后不会在改变,直接从mp中删除,不用再遍历他们了
						it --;//因为少了一位,后面统一位数少一位,所有--
						break;
					}
				}
			}
		}
	}
}

signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);
//	cout.tie(0);
	int t = 1;
//	cin >> t;
	while(t--)
	{
		solve();
	}
}

你可能感兴趣的:(算法)