kuangbin 数学训练一 Answering Queries
题目链接:传送门#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<cmath>#include<bitset>#define ll long longusing namespa
·
题目链接:
传送门
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<bitset>
#define ll long long
using namespace std;
const int N = 100010;
ll ca, t, n, q, arr[N];
int main() {
scanf("%lld", &t);
while(t--) {
//初始化
ll sum = 0;
memset(arr, 0, sizeof arr);
scanf("%lld%lld", &n, &q);
//把一开始序列的sum先加进去
for(ll i = 0; i < n; i++) {
scanf("%lld", &arr[i]);
sum += (n - i - 1) * arr[i];
sum -= i * arr[i];
}
printf("Case %lld:\n", ++ca);
//处理查询和修改
for(ll i = 0; i < q; i++) {
ll op, x, v;
scanf("%lld", &op);
if(op == 1) printf("%lld\n", sum);
else {
scanf("%lld%lld", &x, &v);
//把原来对元素加的次数和减的次数还原
sum -= arr[x] * (n - x - 1);
sum += arr[x] * x;
arr[x] = v;
//把新元素加的次数和减的次数处理进sum中
sum += arr[x] * (n - x - 1);
sum -= arr[x] * x;
}
}
}
}
这道题算是一道数学找规律题吧。
一开始这道题我用暴力做,果然超时了。所以还是老老实实的用数学方法吧
首先在遍历过程中我们可以看看每个数对sum的值的贡献是什么,有时可能是加,有时可能是减。所以我们要统计一下规律每个数作为减的次数有多少次,作为加的次数有多少次,统计一下就会发现每个数作为加的次数就等于n - 所在位置下标。减的次数就等于其下标,因此在加入时,我们让sum += arr[x] * (n - x - 1),sum -= arr[x] * x即可,把数字取出来时则反向操作。
更多推荐
所有评论(0)