CF1637E Best Pair 题解
心理阴影题。考试时写了奇怪的线段树分治,在每个线段树节点上维护单调栈在栈内二分……
这题注意到两维分别是 \(x,cnt_x\),应该对 \(cnt\) 比较敏感的是它的自然根号性质,由于 \(\sum_{cnt_x}=n\),所以实际上 \(cnt_x\) 的种类只有 \(O(\sqrt n)\) 种。我们直接枚举所有这样的对,用一个可删堆来排除掉所有的 bad pair,剩下的最大的拿出来取个 max
就行了。
点击查看代码
const int N=3e5+13;
std::set<int> t[N];
std::map<int,int> no[N];
int n,m,a[N],b[N],c[N];
int main(){int T;read(T);while(T--){
read(n),read(m);
for(int i=1;i<=n;++i) read(a[i]),b[i]=a[i],c[i]=0;
std::sort(b+1,b+n+1);
int tot=std::unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;++i){
a[i]=std::lower_bound(b+1,b+tot+1,a[i])-b;
c[a[i]]++;
}
for(int i=1;i<=n;++i) t[i].clear(),no[i].clear();
for(int i=1;i<=tot;++i) t[c[i]].insert(i);
for(int i=1;i<=tot;++i) no[i][i]=1;
while(m--){
int xx,yy;read(xx),read(yy);
int x=std::lower_bound(b+1,b+tot+1,xx)-b,y=std::lower_bound(b+1,b+tot+1,yy)-b;
if(b[x]!=xx||b[y]!=yy) continue;
no[x][y]=no[y][x]=1;
}
ll ans=0;
for(int i=1;i<=tot;++i){
for(int j=c[i];j;--j){
std::queue<int> q;while(!q.empty())q.pop();
while(!t[j].empty()&&no[i][*t[j].rbegin()]) q.push(*t[j].rbegin()),t[j].erase(*t[j].rbegin());
if(!t[j].empty()) ans=max(ans,((ll)b[i]+b[*t[j].rbegin()])*(c[i]+c[*t[j].rbegin()]));
while(!q.empty()) t[j].insert(q.front()),q.pop();
}
}
println(ans);
}
return 0;
}