翻译:
Stanley决定购买一台由monblock公司生产的新的台式电脑,为了解决他们网站上的验证码问题,他需要解决以下任务。
数组的神奇之处在于数组可以被分割的连续相同数字块的最小数量。例如,数组的强大
[1,1,1]为1;
[5,7]为2,可分为[5]和[7]块;
[1、7、7、7、7、7、7、7、9,9日,9日,9日,9日,9日,9日9,9]是3,因为它可以分成块[1],[7、7、7、7、7、7、7],和[9 9 9,9日,9日,9日,9日9,9]。
给出一个长度为𝑛的数组𝑎。对两个整数𝑖、𝑥有𝑚查询。查询𝑖,𝑥意味着从现在开始数组𝑎的𝑖-th元素等于𝑥。
在每次查询之后,打印数组𝑎的所有子段之间的awesome值的总和。换句话说,在每个查询之后都需要进行计算
∑𝑙= 1𝑛∑𝑟=𝑙𝑛𝑔(𝑙𝑟),
𝑔(𝑙𝑟)数组的精彩𝑏=[𝑎𝑙,𝑎𝑙+ 1,…,𝑎𝑟]。
输入
第一行给出了两个整数𝑛和𝑚(1≤𝑛,𝑚≤105)。
第二行包含𝑛整数𝑎1𝑎2,…,𝑎𝑛(1≤𝑎𝑖≤109)——𝑎数组。
在接下来的𝑚行中,将给出查询的描述。每行包含两个整数𝑖和𝑥(1≤𝑖≤𝑛,1≤𝑥≤109)。
输出
在新一行打印每个查询的答案。
例子
inputCopy
5个5
1 2 3 4 5
3 - 2
4个2
3个1
2 1
2 - 2
outputCopy
29
23
35
25
35
请注意
在第一个查询𝑎等于[1,2,2,4,5]之后,答案是29,因为我们可以按以下方式分割每个子段:
[1;1]:[1], 1块;
[1;2]:[1]+[2], 2块;
[1;3]:[1]+[2,2], 2块;
[1;4]:[1]+[2,2]+[4], 3块;
[1;5]:[1]+[2,2]+[4]+[5], 4块;
[2;2]:[2], 1块;
[2;3]:[2,2], 1块;
[2;4]:[2,2]+[4], 2块;
[2;5]:[2,2]+[4]+[5], 3块;
[3;3]:[2], 1块;
[3;4]:[2]+[4], 2块;
[3;5]:[2]+[4]+[5], 3块;
[4;4]: [4], 1 block;
[4;5]:[4]+[5], 2块;
[5;5]:[5], 1块;
这是1 + 2 + 2 + 3 + 4 + 1 + 1 + 2 + 3 + 1 + 2 + 3 + 1 + 2 + 1 = 29。
题意:根据题意来给的公式不断计算,然后每次单点修改,再次查询。
思路:我们来将数组倒着看,每个相邻不同的对于总贡献是前一个的贡献加上这个数的下标,然后不同的则是前一个的贡献+1,然后可以推出值的改变对总贡献的影响,(i-1)*(n-i+1),然后对于四种情况来进行判断,可能说的不太明白,具体的可以看代码。
代码:
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
using namespace::std;
typedef long long ll;
inline __int128 read(){
__int128 x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(__int128 x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
int n,m;
ll ss[100005];
ll sr[100005];
ll sum=0;
ll q,w;
int main(){
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
cin>>n>>m;
int kl=n;
for (int i = kl; i>=1; i--) {
cin>>ss[i];
}
sr[1]=1;
for (int i =2; i<=n; i++) {
if (ss[i]!=ss[i-1]) {
sr[i]=sr[i-1]+i;
}
else{
sr[i]=sr[i-1]+1;
}
}
for (int i =1; i<=n; i++) {
sum+=sr[i];
}
while (m--) {
cin>>q>>w;
q=n-q+1;
if (w==ss[q]) {
printf("%lld\n",sum);
continue;
}
if (ss[q]==ss[q-1]&&q-1>0) {
sum+=(q-1)*(n-q+1);
}
if (ss[q]==ss[q+1]&&q+1<=n) {
sum+=q*(n-q);
}
if (w==ss[q+1]&&ss[q]!=ss[q+1]&&q+1<=n) {
sum-=q*(n-q);
}
if (w==ss[q-1]&&ss[q]!=ss[q-1]&&q-1>0) {
sum-=(q-1)*(n-q+1);
}
ss[q]=w;
printf("%lld\n",sum);
}
return 0;
}