summer vacation rating 1

C题
(关于不重复子串)
题目描述:
奥雅纳必须为他的计算机科学1班的学生做许多练习题。因为很多问题都是关于数组的,所以他必须为他的学生生成数组。因为他不想给他们难题的练习,他总是保证(给学生的)数组有唯一的值。也就是说,任何值都不会在他的数组中出现两次。

不幸的是,奥雅纳在生成数组方面太懒了!大约20年前,当他开始教授计算机科学的时候,他做了一个很长的数组来重用,但是这个长数组可能有重复的值。当他制造问题时,他只是简单地抓取这个长数组的一个连续子序列作为用于解决问题的数组,但他需要确保这个连续子序列不包含重复项。如果长数组有项a[0], a[1],…,a[n-1],则长数组的连续子序列是任意包含j-i+1项a[i], a[i+1],…,a[j]的序列,其中0≤i≤j≤n-1。

给定一个由n个整数组成的数组,确定数组中有多少个连续子序列不包含任何重复值。注意,如果两个具有相同内容的子序列开始于原始长数组的不同位置,则认为它们是不同的(即都计入总数)。

输入描述:
第一行包含一个正整数n(1≤n≤1e5),表示输入数组的大小。下面一行包含n个以空格分隔的整数,表示
输入数组,按它们在数组中出现的顺序排列。每个数组值都将是1到1e18之间的整数(包括1和1e18)。
(注:1e5的意思是1乘以10的5次方,也就是100000)

输出描述:
单独在一行上,输出不包含任何重复值的输入数组的连续子序列的总数。
在这里插入图片描述
在这里插入图片描述
题解:
这个题就是说给你一个字符串然后你找它的子串,统计每个字符都不一样的子串个数。
首先如果考虑暴力的话可以先把它的子串全部都找出来,然后看哪个子串是符合要求的然后统计子串的个数,但是这样肯定会超时,所以我们对于样例一个一个的分析,看看找到其中的规律

思路:
用一次for循环记录从1到n,在每一个i位置的子串数量
举例:
1 2 3
1 到该位置的子串个数为1:只有1一个
2 到该位置的子串个数为2:有 12,2
3 到该位置的子串个数为3:有 123,23,3
由该规律可得:
到 i 位置的子串个数为从最后一个不重复的元素的位置开始到 i 位置距离的长度
定义变量 m 记录最后一个不没有重复的元素的位置
注意:
map可以当做二维数组来用,自动排序(从小到大)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll MAXN=1e5+5;
map<ll,ll> m1;
ll num[MAXN];
int main()
{
    ll n;
    cin>>n;
    for(ll i=1; i<=n; i++)
    {
        cin>>num[i];
    }
    ll sum=0;
    ll m=0;
    for(ll i=1; i<=n; i++)
    {
        if(m1[num[i]]==0)
        {
            sum+=i-m;
            m1[num[i]]=i;//根据元素的位置求该位置极其以前的不重复子串
        }
        else
        {
            m=max(m,m1[num[i]]);
            sum+=i-m;
            m1[num[i]]=i;//记录最后一个重复元素的前一个相同元素的位置
        }
    }
    cout<<sum<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值