CF1637E Best Pair
Posted solemntee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1637E Best Pair相关的知识,希望对你有一定的参考价值。
题意:给你一个多重集,求
(
x
+
y
)
×
(
c
n
t
x
+
c
n
t
y
)
(x+y)\\times(cnt_x+cnt_y)
(x+y)×(cntx+cnty)的最大值,其中
x
!
=
y
x!=y
x!=y且有
m
m
m对
(
x
,
y
)
(x,y)
(x,y)是不能选的
首先枚举
(
x
,
y
)
(x,y)
(x,y)是
O
(
N
2
)
O(N^2)
O(N2)的,我们考虑枚举
(
c
n
t
x
,
c
n
t
y
)
(cntx,cnty)
(cntx,cnty),因为不同的
c
n
t
x
cntx
cntx是
O
(
N
)
O(\\sqrt N)
O(N)的,先枚举
(
c
n
t
x
,
c
n
t
y
)
(cnt_x,cnt_y)
(cntx,cnty)。对于出现次数为
c
n
t
x
cnt_x
cntx数量的数字可以从大到小贪心选取。
构建一个优先队列,初始
p
u
s
h
(
1
,
1
)
push(1,1)
push(1,1),表示
c
n
t
x
cnt_x
cntx集合中最大的数和
c
n
t
y
cnt_y
cnty集合中最大的数。(这个过程和那个轮廓线+优先队列的过程非常像),如果
(
1
,
1
)
(1,1)
(1,1)非法就继续放入
(
1
,
2
)
和
(
2
,
1
)
(1,2)和(2,1)
(1,2)和(2,1)重复该操作直到找到第一个合法的,就是
c
n
t
x
cnt_x
cntx和
c
n
t
y
cnt_y
cnty的最大值。这样就可以
O
(
N
+
M
l
o
g
(
M
)
)
O(N+Mlog(M))
O(N+Mlog(M))完成。
其实感觉下来还是很简单写意的,写起来可能稍微有一些细节。
D题太简单就不水了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node
int x,y;
int val;
bool operator<(const node &ths)const
return val<ths.val;
;
int main()
int T;
scanf("%d",&T);
while(T--)
int n,m;
scanf("%d%d",&n,&m);
vector<int>a(n+1);
map<int,int>mp;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
mp[a[i]]++;
set<pair<int,int>>bad;
for(int i=1;i<=m;i++)
int tu,tv;
scanf("%d%d",&tu,&tv);
if(tu>tv)swap(tu,tv);
bad.insert(tu,tv);
for(int i=1;i<=n;i++)bad.insert(a[i],a[i]);
int N=sqrt(n);
vector<pair<int,int>>huge;
vector<vector<int>>small(N+1);
for(auto [fi,se]:mp)
if(se<N)small[se].push_back(fi);
else huge.push_back(fi,se);
for(int i=1;i<N;i++)sort(small[i].begin(),small[i].end(),greater<int>());
ll ans=-1e18;
for(int size=2;size<=2*N-2;size++)
for(int sizex=1;sizex<min(size,N);sizex++)
int sizey=size-sizex;
if(sizey<N&&sizex<=sizey)
int mark1=0,mark2=0;
set<pair<int,int>>vis;
priority_queue<node>q;
if(mark1<small[sizex].size()&&mark2<small[sizey].size())
q.push(mark1,mark2,small[sizex][mark1]+small[sizey][mark2]);
vis.insert(mark1,mark2);
while(!q.empty())
auto [x,y,val]=q.top();
int tx=small[sizex][x],ty=small[sizey][y];
if(tx>ty)swap(tx,ty);
if(bad.count(tx,ty))
if(x+1<small[sizex].size()&&vis.count(x+1,y)==0)
q.push(x+1,y,small[sizex][x+1]+small[sizey][y]);
vis.insert(x+1,y);
if(y+1<small[sizey].size()&&vis.count(x,y+1)==0)
q.push(x,y+1,small[sizex][x]+small[sizey][y+1]);
vis.insert(x,y+1);
else
ans=max(ans,1LL*size*val);
break;
q.pop();
for(int i=0;i<huge.size();i++)
for(int j=i+1;j<huge.size();j++)
auto [num1,cnt1]=huge[i];
auto [num2,cnt2]=huge[j];
if(bad.count(num1,num2)==0)ans=max(ans,1LL*(1LL*num1+num2)*(1LL*cnt1+cnt2));
for(int i=0;i<huge.size();i++)
auto [NUM,cnt]=huge[i];
for(int j=1;j<N;j++)
for(auto num:small[j])
if(bad.count(min(num,NUM),max(num,NUM))==0)
ans=max(ans,1LL*(1LL*NUM+num)*(1LL*cnt+j));
break;
printf("%lld\\n",ans);
return 0;
以上是关于CF1637E Best Pair的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Global Round 19 E. Best Pair