zoukankan      html  css  js  c++  java
  • Zigzags CodeForces

    给出一组数:

    寻找四元组的个数 

    (i,j,k,l)其中a[i]=a[k],并且a[j]=a[l]

    刚看到这个题的时候想到了记录每个数的个数,然后求前缀和以及后缀和。先枚举i和k,当a[i]和a[k]相等时,在枚举i和k之间的数,然后在将前缀和与后缀和相乘,但是这样复杂度是o(n^3),显然过不了。看了大佬的blog,发现有个更好的思路,我们现在枚举了i和k对吧,i-----k,而题目的要求是k---i---k---i,那就直接在i左边找个K并且在k后边找个i然后将他们出现的次数相乘就完了呗!

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e3+7;
    long long  preious_sum[N][N];//表示sum[i][j]表示前i个数,j出现的次数
    long long later_sum[N][N];
    int arr[N];
    int main(){
        int t;
        cin>>t;
        while(t--){
            int n;
            cin>>n;
            for(int i=1;i<=n;i++) {
                cin>>arr[i]; 
                preious_sum[i][arr[i]]++;
                later_sum[i][arr[i]]++; 
            }
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    preious_sum[i][j]+=preious_sum[i-1][j];
                } 
            }
            for(int i=n;i>=1;i--){
                for(int j=1;j<=n;j++){
                    later_sum[i][j]+=later_sum[i+1][j];
                } 
            }
            long long  ans=0;
            for(int i=1;i<=n;i++){
                for(int j=i+1;j<n;j++){
                    ans+=preious_sum[i-1][arr[j]]*later_sum[j+1][arr[i]];
                }
            }
            cout<<ans<<endl;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++)
                    later_sum[i][j]=preious_sum[i][j]=0;
            }
        }
    
    
        return 0;
    }

     另外一种写法。

    code:

    #include <stdio.h>
    #define maxn 3010
    #define LL long long
    int a[maxn],cnt[maxn];
    int main(){
        int t,n,i,j,sum;
        LL ans;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            for(i=1;i<=n;i++)scanf("%d",&a[i]);
            for(i=1;i<=n;i++)cnt[i]=0;
            ans=0;
        //i1---j2
        //当前循环枚举的是i1和j2,cnt[]记录的是a[i1]出现的次数.
        //j1---i1---j2---i2
        //当枚举到i1=i,j2=j时,sum记录的是从i到j各个数出现的和,而cnt[k]就是在i1之前元素k出现的次数。sum累加就相当于寻找a[j1]=a[j2]的过程
        //当a[i]==a[j]的时候,说明i2找到了,i2=j,然后就可以更新答案了,更新完之后,j继续往后,因为后边可能还会有和a[i]相等的元素,找到再累加。
            for(i=1;i<=n;i++){
                sum=0; 
                for(j=i+1;j<=n;j++){
                    if(a[i]==a[j])ans+=sum;
                    sum+=cnt[a[j]];
                }
                cnt[a[i]]++;//第i个数出现的次数
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解
    大型网站系统架构技术原理透析
    大中型网站架构探秘
    大型网站架构不得不考虑的10个问题
    (推荐)高并发高流量网站架构详解
    可扩展、高可用、负载均衡网站架构设计方案
    nginx内置常用变量
    Linux下nginx支持.htaccess文件实现伪静态的方法!
    扩展js,实现c#中的string.format方便拼接字符串
    Winform退出运行后,删除运行目录(批处理方法)
  • 原文地址:https://www.cnblogs.com/Accepting/p/13599121.html
Copyright © 2011-2022 走看看