ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces 1637 E. Best Pair —— 思维

2022-02-23 20:35:18  阅读:227  来源: 互联网

标签:check ll mid Codeforces ans Pair mx Best first


This way

题意:

给你n个数,cnt[i]表示i出现的次数。
求出最大的(x+y)*(cnt[x]+cnt[y])
x不等于y并且给你一些不能取的对数。

题解:

一开始想的是那种随着值增大出现次数单调递减的二分。但是这种不能取的情况一旦出现就导致可能不是最优的,那么二分怎么做我一下子就想不出来了。
值想不出来换个思路,通过出现次数枚举,我们会发现不同种类的出现次数最多只有 O ( n ) O(\sqrt{n}) O(n ​)次。
最坏情况应该是这样:出现1次的有1个,2次的有1个,3次的有1个…那情况数为(1+x)*x/2<=n。
然后我们由于要使乘积最大,对于相同出现次数的我们只需要找最大的就好了。但是这里有一个问题就是说有不能取的对,所以对于相同出现次数的,我们还是要值从高往低找到能取的值。由于这个时间复杂度是独立的,所以总时间复杂度就是O(NlogN)。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=3e5+5;
const ll M=1e9+7;
struct node{
    ll val,num;
}a[N];
#define pll pair<ll,ll>
struct pair_hash{
    template<class T1,class T2>
    std::size_t operator()(const std::pair<T1,T2>&p)const {
        auto h1 = std::hash<T1>{}(p.first);
        auto h2 = std::hash<T2>{}(p.second);
        return h1*M+h2;
    }
};
unordered_map<pll,ll,pair_hash>mp;
unordered_map<ll,ll>num;
ll check(ll x,ll i){
    return (a[x].val+i)*(a[x].num+num[i]);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        num.clear();
        mp.clear();
        int n,k;
        ll x,y;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)scanf("%lld",&x),num[x]++;
        for(int i=1;i<=k;i++)
            scanf("%lld%lld",&x,&y),mp[{x,y}]=mp[{y,x}]=1;
        ll all=0,mx=0;
        for(auto i :num){
            int l=1,r=all,ans=0,mid;
            if(all){
                while(r>=l){
                    mid=l+r>>1;
                    if(!ans)ans=mid;
                    if(check(mid,i.first)>check(ans,i.first))
                        ans=mid;
                    if(check(mid,i.first)>=check(mid+1,i.first))r=mid-1;
                    else l=mid+1;
                }
                if(mp[{i.first,a[ans].val}]){
                    l=r=ans;
                    while(l&&mp[{i.first,a[l].val}])l--;
                    while(r<=all&&mp[{i.first,a[r].val}])r++;
                    if(l)mx=max(mx,check(l,i.first));
                    if(r-all-1)mx=max(mx,check(r,i.first));
                }
                else
                    mx=max(mx,check(ans,i.first));
            }

            while(all&&i.second>=a[all].num)all--;
            a[++all]={i.first,i.second};
        }
        printf("%lld\n",mx);
    }
    return 0;
}

标签:check,ll,mid,Codeforces,ans,Pair,mx,Best,first
来源: https://blog.csdn.net/tianyizhicheng/article/details/123097753

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有