• 2019牛客暑期多校训练营(第八场)B-Beauty Values(期望线性性)


    >传送门<

    题意:
    思路:期望的线性性(可加性)比赛的时候写的代码超级无敌长,不过值得欣慰的是一发AC了,官方的题解写的还不错~

    我们可以把每种数字对答案的贡献分开来计算,即枚举每个数字,求原序列有多少个子区间包含至少一个该 数字,最后把答案累加起来即可。

    问题在于求序列有多少个子区间包含至少一个某数字,既可以直接计算,也可以考虑用全集减去不包含的子区间。不包含的子区间的个数可以枚举相邻两个数字,并累加中间空隙的子区间个数,再统计一下边界即可。 时间复杂度为O(n)

    下面给出直接计算的代码

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll v[100005];
    int main()
    {
        int n;
        cin>>n;
        ll ans = 0, a;
        for(int i=1;i<=n;i++){
            cin>>a;
            ans += (n-i+1)*(i-v[a]);
            v[a] = i;
        }
        cout<<ans<<endl; 
    }

    n-i+1表示的是当前数字a能影响到的后面区间数量,i-v[a](避免重复计算)表示的是当前a向左延伸直到上一个a间的区间数量+空区间,两者相乘即得到当前数字能影响到的区间,最后把每个数字相加起来就是答案。

    举个栗子,就拿题目中的[1,2,1,3]来说

    当扫描到i = 3时,这个1能影响到的区间有[3,3] = {1},[3,4] = {1,3},[2,3] = {2,1},[2,4] = {2,1,3},[1,3] = {1,2,1},[1,4] = {1,2,1,3}

    但是你马上会发现此时这个1能影响到的区间和第一个1能影响的区间有一部分重合了,怎么办?

    那我就只让这个1影响的区间向左扩散,直到碰到1就停下,即向左扩散只影响这两个1间的区间就行了

    对于[7,6,2,1,3,4,1,5,9]而言

    当i = 7,v[a] = 4(上一个a的位置),向后影响到9-7+1=3个区间( {1},{1,5},{1,5,9} ),向前影响到7-4=3个区间( {Ø},{2},{6,2},{7,6,2}),总共能影响到9个区间

  • 相关阅读:
    面试题
    Tornado中insert into sql语句的构造
    依赖注入
    Tornado抽象方法抽象类
    mysql 随机选取一条记录
    java中如何高效的判断数组中是否包含某个元素---
    Java8中计算日期时间差
    MySQL5.7中使用JSON
    sql中的in与not in,exists与not exists的区别
    APP开发浅谈-Fiddler抓包详解
  • 原文地址:https://www.cnblogs.com/wizarderror/p/11340957.html
Copyright © 2020-2023  润新知