鸡格线 (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, m ≤ 105),表示数组长度与操作次数。
接下来一行输入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<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stack>
#include<cstdio>
#include<string>
#include<cstdio>
#include<cmath>
#include<map>
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N = 5e5 + 10;
int n,m;
void solve()
{
cin >> n >> m;
map<int,int> 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();
}
}