Zigzags CodeForces - 1400D 思维

题意

给出一组数:
寻找四元组的个数
(i,j,k,l)其中a[i]=a[k],并且a[j]=a[l]
且 1 <= i < j < k < l <= n ;

思路

四个数 分别为 a1 b1 a2 b2 其中 a1=a2 b1=b2
先枚举b1的位置(从 i = 2开始,因为前面必须有数当a1)
然后从 j = i+1位置开始遍历到j=n,找与b1相等的数
若num[ i ] = num[ j ],则代表找到了 b2,那么此时更新答案ans

那么怎么更新答案呢
我们在 j 开始遍历时,记录每一个位置的数在前面出现的次数的总和sum
因为 一个数前面出现过几次 就代表 有几组 (a1, a2)

在b1 b2确定之后(即num [ i ] =num [ j ]时) i+1 ~ j-1之间的数都可以是a2 那么每一个a2 又可能有多个a1与其对应(a2 这个数在之前出现过几次 就有几个a1 与其对应) ,所以sum就是 每一对确定的 b1 b2 对应的合题意的四元组的组数

综上:
枚举b1 对于每一个b1 ,初始化sum=0 ,遍历找b2,遍历的同时,记录可能的(a1,a2)的组数sum 成功找到一个 b2,就更新答案 ans+=sum; 遍历完成后,更新b1这个数的出现次数

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#define mm 1000000007
using namespace std;
typedef long long ll;
int a[3010],cnt[3010];///a:原数组   cnt:次数数组  目前 i 出现过几次
///a1 b1 a2 b2
int main()
{
    int t,x;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&x);
        for(int i=1;i<=x;i++)
        {
            scanf("%d",&a[i]);
            cnt[i]=0;
        }
        ll ans=0,sum=0;
        cnt[a[1]]=1;///a[1]这个元素出现过1次
        for(int i=2;i<x;i++)///枚举b1
        {
            sum=0;///sum为对于每一个固定的i 合题意的组数
            for(int j=i+1;j<=x;j++)///枚举a2
            {
                if(a[i]==a[j])ans+=sum;///找到b2 更新答案
                sum+=cnt[a[j]];///前面a[j] 出现cnt【】次,就有cnt组
            }
            cnt[a[i]]++;
        }

        printf("%lld\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值