• Managing Difficulties(mp的变形+三元组)


    Every day a new programming problem is published on Codehorses. Thus, n problems will be published in the following n days: the difficulty of the i-th problem is ai.
    Polycarp wants to choose exactly three days i, j and k (i < j < k) so that the difference of difficulties on the day j and the day i is equal to the difference of difficulties on the day k and day j. In other words,Polycarp wants equality aj − ai = ak − aj to be true.
    Determine the number of possible ways for Polycarp to choose the three days in the desired way.

    输入

    The first line contains an integer t — the number of test cases in the input (1 ≤ t ≤ 10). Then t test case descriptions follow.
    The first line of a test case contains an integer n — the number of the days (3 ≤ n ≤ 2000).
    The second line of the test case contains n integers a1, a2, ... , an, where ai is the difficulty of the problem on the i-th day (1 ≤ ai ≤ 109).

    输出

    Output t integers — the answers for each of the test cases in the input, in the order they are given. The answer to a test case is the number of triples of indices i, j, and k such that 1 ≤ i < j < k ≤ n and
    ak − aj = aj − ai. 

    样例输入 Copy

    4
    5
    1 2 1 2 1
    3
    30 20 10
    5
    1 2 2 3 4
    9
    3 1 4 1 5 9 2 6 5
    

    样例输出 Copy

    1
    1
    4
    5

    题目的意思就是让你找一个三元组i,j,k,使得ak − aj = aj − ai.暴力肯定要超时,显然要对式子变形。 

    1.一开始是做的时候我们做的时候就是变成2*a[j]=a[k]+a[i]就是枚举a[k]和a[i]。用一个前缀和的思想预处理出来a[k]到a[i]的
    中a[j]的个数
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    unordered_map<ll,ll> mp;
    inline ll read(){
        ll  x=0;
        bool f=0;
        char ch=getchar();
        while (ch<'0'||'9'<ch)    f|=ch=='-', ch=getchar();
        while ('0'<=ch && ch<='9')
            x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    ll a[2010],f[2010][2010];
    int main()
    {
        ll t;
        t=read();
        while(t--)
        {
            memset(a,0,sizeof a);
            int n;
            n=read();
            int s = 0;
            for(int i=1;i<=n;i++)
            {
                a[i]=read();
                if(!mp[a[i]]) mp[a[i]]=++s;
            }
            memset(f,0,sizeof f); 
            for(int i=1;i<=s;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    //f[i][j]表示前j项中有多少个i
                    if(mp[a[j]]==i) f[i][j]=f[i][j-1]+1;
                    else f[i][j]=f[i][j-1];
                }
            }
            ll ans=0;
            for(int i=1;i<=n-2;i++)
            {
                for(int k=i+2;k<=n;k++)
                {
                    ll tmp=a[i]+a[k];
                    if(tmp%2!=0) continue;
                    ll val=tmp/2;
                    ll idx=mp[val];
                    ll num=f[idx][k-1]-f[idx][i];
                    ans+=num;
                }
            }
            printf("%lld
    ",ans);
            mp.clear();
        }
        return 0;
     }

    2.正解就是让a[i]=2*a[j]-a[k],就一个map就解决了,太妙了

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<map>
    #include<cstdio>
    #include<iostream>
    #include<queue> 
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    template <typename Tp>
    void read(Tp &x){//read(n);
        x=0;char ch=1;int fh;
        while(ch!='-'&&(ch>'9'||ch<'0')){
            ch=getchar();
        }
        if(ch=='-'){
            fh=-1;ch=getchar();
        }else fh=1;
        while(ch>='0'&&ch<='9'){
            x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
        }
        x*=fh;
    }
    inline char read1()//字符串读入挂
    {
        register char ch=getchar();
        while(ch<'A'||ch>'M')ch=getchar();
        return ch; 
    }
    const int maxn=1e6+100;
    const int mod=1000000007;
    int a[maxn];
    map<int,int>mp;
    int main()
    {
        ll t;
        read(t);
        while(t--){
            mp.clear(); 
            int n;
            cin>>n;
            for(int i=1;i<=n;i++){
                cin>>a[i];
            }
            mp[a[1]]=1;
            int ans=0;
            for(int j=2;j<=n;j++){
                for(int k=j+1;k<=n;k++){
                    int temp=2*a[j]-a[k];
                    if(temp<0||mp[temp]==0){
                        continue;
                    }
                    ans+=mp[temp];
                }
                mp[a[j]]++;//这样就能找出j之前的a[i]的个数 
            } 
            cout<<ans<<endl;
        }
        return 0;
     }


  • 相关阅读:
    网络通讯协议的基本要素
    java实现二维码的生成与解析
    SpringCloud应用间通信-RestTemplate与Feign
    SpringCloud服务注册与发现-Eureka、Nacos和Consul
    极光推送-java消息推送app
    Git的回滚和撤销操作
    SOFABoot学习
    记录一次生产环境下EleasticSearch故障(cpu打满)
    记录SQL优化
    利用二进制存储多种状态
  • 原文地址:https://www.cnblogs.com/lipu123/p/13796283.html
Copyright © 2020-2023  润新知