• nyoj 975 Distinct Count


    Distinct Count

    时间限制:3000 ms  |  内存限制:65535 KB
    难度:3
    描述
    给一个长度为 n 的数列 {an} ,找出有多少个长度为 m 的区间,使区间中不含有重复的数字。
    输入
    多组测试数据。(200组)
    第 1 行有 2 个数,n,m。(1<=n,m<=10^5)
    接下来 1 行有 n 个数,ai。(|ai|<=10^9)
    输出
    1 行有 1 个数,满足条件的区间的个数。
    样例输入
    6 3
    1 6 2 6 3 6
    样例输出
    2
    讲解:昨天下午和晚上,我和zz都在想这道题,昨天夜里睡觉之前想了下,还是没思路,今天早晨读书时突发灵感啊,算是想清楚了,嘎嘎,特来纪念一下;
    我们可以采用左减,右加的方式来解决;依次向右滑动;
    线把前m个出现的数标记成1,当然会有重复的,于是用 map 进行计重;map的指向为与之相同前一个数的下标;
    也就是说把n个中出现多次的数,只把,最后一个数,标记为1,前面的都为0;然后求和时,这个数,就算了一次;
    案例:sum 每 n个数的和;
    7 3
    1 6 2 6 3 6 7
    1 1 1 sum=3;
    1 0 1 1 sum=sum-b[1] =2
    1 0 1 1 1 sum=sum+1-b[2]=3
    1 0 1 0 1 1 sum=sum-b[3] =2 //当前的已经出现过了,不在加了,只减去前面的
    1 0 1 0 1 1 1 sum=sum+1-b[4]=3

    AC代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<string>
     6 #include<cmath>
     7 #include<map>
     8 #include<queue>
     9 using namespace std;
    10 const int N=1e5+5;
    11 int a[N],b[N];
    12 int main()
    13 {
    14     int ans,sum,m,n;
    15     map<long long ,int >ma;
    16     while(cin>>m>>n)
    17     {
    18         ma.clear();
    19         memset(b,0,sizeof(b));
    20         sum=0;ans=0;
    21         for(int i=1 ; i<=m ;i++)
    22         {
    23             scanf("%d",&a[i]);
    24             if(i<=n)
    25             {
    26             if(ma[ a[i] ]==0)
    27             {
    28                 sum=sum+1;             //统计前n个共有几个数;
    29                 ma[ a[i] ]=i;          //标记一下,下标;
    30                  b[i]=1;               //如果此数没有出现,标记为1;
    31             }
    32             else {
    33                       b[ ma[i] ]=0;   //如果已经出现了,把前面的标记为0;
    34                       b[i]=1;         //当前的为1;
    35                       ma[ a[i] ]=i;   //并更新下标,方便下一次更新;
    36                  }
    37             }
    38         }
    39 
    40         if(n==1)
    41         { printf("%d
    ",m);continue;}
    42         if(sum==n)
    43           ans++;
    44         for(int i=n+1,j=1; i<=m ; i++,j++)
    45         {
    46             if(ma[a[i]]==0)//前面没有出现过,直接更新sum,b,ma
    47             {
    48                 sum=sum+1;
    49                 ma[ a[i] ]=i;
    50                 b[i]=1;
    51             }
    52             else {       //出现过了的,前面相同的更新为0,同时更新为新的下标,当前位置标记为1;
    53                 b[ma[a[i]]]=0;
    54                 ma[a[i]]=i;
    55                 b[i]=1;
    56             }
    57             sum=sum-b[j];    //减去最前面的数,就是这n个数的和;然后判断 sum是否等于n;
    58             if(sum==n)
    59                 ans++;
    60         }
    61         cout<<ans<<endl;
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    python3之datetime模块
    python3之time模块
    前端面试题01
    前端面试题02
    angularjs
    nodejs
    android 报错记录
    android知识点回顾二
    android知识点回顾
    Broadcast广播代码例子
  • 原文地址:https://www.cnblogs.com/lovychen/p/3718065.html
Copyright © 2020-2023  润新知