cf Sonya and Robots

题目网址点击打开链接

    题目意思是给你一个序列,要从左边数起第一个a的位置要在从右边数起第一个b的位置的前面,让你求(a,b)这样的一对数的种数是多少。

    序列里的每个数都可以和他后面的全部数组成(a,b),但是有重复。重复分2种,一种是(2,3,3)这种情况,可以组成2个(2,3),但是有重复就只算1种,要避免这种情况就要维护每一个数字后面数的种类。一种是(3,3,2)这种情况,可以组成(3,3)和(3,2)和(3,3)但是有重复只算2种,要避免这种情况就要用vis数组,假如一个数已经做过一次a了,那么下次就不能做a了。做法就是对这个序列进行桶排序,但并不是获取这个序列的升序或减序序列,是要记录下这个序列的每种数的个数,以及这个序列的数的种数,另外还设了一个标记数组标记哪些数字做过a了。

    从头到尾扫一遍,用cnt维护该数字后面的数的种类,然后cnt即是该数字可以和后面的数组成(a,b)的种数,然后判断一下该数字是否做过a了,做过了的话就跳过该数字,若是没做过就ans+=cnt,然后给该数组标记。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,a[maxn],t[maxn],vis[maxn];//t数组表示桶数组
int main()
{
    long long cnt=0,ans=0;
    cin>>n;
    for(int i=0;i<n;i++)//桶排序,在桶排序的过程中统计序列中有多少种数
    {
        cin>>a[i];
        if(t[a[i]]==0)
        {
            cnt++;
        }
        t[a[i]]++;
    }
    for(int i=0;i<n;i++)
    {
        t[a[i]]--;
        if(t[a[i]]==0)  cnt--;
        if(!vis[a[i]])
        {
            ans+=cnt;
            vis[a[i]]=1;
        }
    }
    cout<<ans<<endl;
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_40642465/article/details/80950476
今日推荐