cunzai_zsy0531

关注我

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;
}
posted @ 2022-05-30 11:23  cunzai_zsy0531  阅读(84)  评论(0编辑  收藏  举报