返回顶部

Educational Codeforces Round 94 (Rated for Div. 2) D. Zigzags (枚举,前缀和)

  • 题意:有一长度为\(n(4\le n\le 3000)\)的数组,选择四个位置\((i,j,k,l)\ (1\le i<j<k\le n)\),使得\(a_i=a_k\)并且\(a_j=a_l\),问存在多少这样的元祖.

  • 题解:\(n\)最大给了\(3000\),所以时间复杂度最坏可以是\(O(n^2)\),我们可以考虑枚举\(i,j,k,l\)的某两个,如果枚举\(i\)\(j\),那么可以确定\(a_k\)\(a_l\),但是不知道位置,同理\(i,k\)\(j,l\)\(k,l\)都不行,只有当我们枚举\(j,k\)时可以确定\(a_i\)\(a_l\)的值,\(i\)的位置在\([1,j-1]\),\(l\)的位置在\([k+1,n]\),位置和值我们都能同时确定.所以我们可以枚举\(j\)\(k\),然后在\([1,j-1]\)中寻找与\(a_j\)相同的元素个数,在\([k+1,n]\)中寻找与\(a_k\)相同的元素的个数,这两个寻找的操作我们可以通过前缀和来处理,所以寻找的复杂度是\(O(1)\).这样这题就这么被我们解决啦~.

  • 代码:

    #define int long long 
     
    int t;
    int n;
    int a[N];
    int pre[3010][3010];
     
    signed main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        cin>>t;
        while(t--){
            cin>>n;
            me(pre,0,sizeof(pre));
            for(int i=1;i<=n;++i) cin>>a[i];
     
            for(int i=1;i<=n;++i){
                pre[i][a[i]]++;
                for(int j=i+1;j<=n;++j){
                    pre[j][a[i]]=pre[i][a[i]];
                }
            }
       
            int ans=0;
     
            for(int j=2;j<=n-1;++j){
                for(int k=j+1;k<=n;++k){
                    ans+=pre[j-1][a[k]]*(pre[n][a[j]]-pre[k][a[j]]);
                }
            }
     
            cout<<ans<<'\n';
     
        }
     
        return 0;
    }
    
posted @ 2020-11-06 22:40  Rayotaku  阅读(69)  评论(0编辑  收藏  举报