Codeforces Round #816 (Div. 2) C. Monoblock

Codeforces Round #816 (Div. 2) C. Monoblock_第1张图片

 Codeforces Round #816 (Div. 2) C. Monoblock_第2张图片

翻译:

 

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)。

第二行包含整数12,…,(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 
#include 
#include 
#include 
#include 
#include 
#include
#include
#include
#include
#include
#include
#include
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;
}

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