首页 > 其他分享 >CF1715C

CF1715C

时间:2023-01-23 22:33:23浏览次数:61  
标签:ch const int ll 贡献 CF1715C define

*1700

Monoblock - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

首先看数据范围  1≤n,m≤1e5。

主要是修改1e5,查询1e5,这里的话要么O (log) 做法,要么O(1)做

O(log)没有什么好方法,那就是O(1)做法。

通过O(1)做法,联想单点修改,单点统计。(套路,但要学过) 

这道题比较妙的点:

比如对于统计  [1,7,7,7,7,7,7,7,9,9,9,9,9,9,9,9,9] ,我们把连续相同数字的第一个数,作为对答案的贡献值

现在我们枚举第i位的a[i]对答案的贡献,O(1)统计

一:对于 [i~i] , [i~i+1] , [i~i+2] , [i~i+3] …… [i~n-1],[i~n]的这些序列,i下标就是一个出现a[i]值的位置,对于答案的贡献就是 n-i+1

二:再考虑(1~i-1)的位置,如果a[i-1]!=a[i],那么对(1~i-1)有贡献,否则a[i]对(1~i-1)不会有贡献,因为有a[i-1]的存在

那么如果a[i-1]!=a[i],对于(1~i-1)的位置,根据数学组合,应该有 len(1,i-1)(枚举左端点~a[i])len(i,n)(a[i]~枚举右端点)

ll calc(int i)
{
    //这里的关键:例如:对于 1,2,2,2,3,3,3,3 我们比第一个出现的当作贡献值,下标 1,2,5 就是对答案的贡献 
    if(a[i]==a[i-1]) return n-i+1;
    else return 1LL*(i-1)*(n-i+1)+n-i+1;
}

 

对于修改,如果对第i位进行了修改,那么只会对第i位和第i+1的答案贡献有影响,我们只需先删去原本的答案贡献,再加上修改后的答案贡献即可

    for(int i=1;i<=m;i++)
    {
        int  k=read(),x=read();
        ans-=calc(k)+calc(k+1);
        a[k]=x;
        ans+=calc(k)+calc(k+1);
        printf("%lld\n",ans);
    }

 

Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back   //vector函数
#define popb pop_back  //vector函数
#define fi first
#define se second
const int N=1e5+10;
//const int M=;
//const int inf=0x3f3f3f3f;     //一般为int赋最大值,不用于memset中
//const ll INF=0x3ffffffffffff; //一般为ll赋最大值,不用于memset中
int T,n,m,a[N];
ll sum[N];
inline int read()
{
    int 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<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
ll calc(int i)
{
    //这里的关键:例如:对于 1,2,2,2,3,3,3,3 我们比第一个出现的当作贡献值,下标 1,2,5 就是对答案的贡献 
    if(a[i]==a[i-1]) return n-i+1;
    else return 1LL*(i-1)*(n-i+1)+n-i+1;
}
int main()
{
//    freopen("","r",stdin);
//    freopen("","w",stdout);
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    ll ans=0;
    for(int i=1;i<=n;i++) ans+=calc(i);
    for(int i=1;i<=m;i++)
    {
        int  k=read(),x=read();
        ans-=calc(k)+calc(k+1);
        a[k]=x;
        ans+=calc(k)+calc(k+1);
        printf("%lld\n",ans);
    }
    return 0;
}

 

标签:ch,const,int,ll,贡献,CF1715C,define
From: https://www.cnblogs.com/Willette/p/17065636.html

相关文章

  • CF1715C 题解
    前言题目传送门!更好的阅读体验?简单的数学题。思路每次只变一个数,因此考虑在短时间内计算:每个位置的数产生的贡献。容易发现以下的条件:不管\(a_i\)是什么,当它作......
  • CF1715C Monoblock 题解
    思路根据题意我们不难看出,求一个区间的块的数量即求区间内\(a_i\neqa_{i-1}\)的数量,如果直接枚举每个区间的话,时间复杂度是\(\mathcalO(n^2)\)显然这样做是不行的,但......