BZOJ5362: [Lydsy1805月赛]quailty 算法

https://lydsy.com/JudgeOnline/problem.php?id=5362

分析:

  • 题意即求一个最小基环树森林,两点之间边权为异或值。
  • 这题的思路很好,先排序,我们二进制分组,将\(0\)和\(1\)分成两部分,显然这两部分之间的边能不连就不连。
  • 但也有必须连的情况,就是出现某个集合大小小于等于\(2\)的情况,内部无法自身构成基环树,需要和另外一个集合连边,此时我们暴力找最小的边即可。
  • 时间复杂度为\(O(nlogn)\)。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 300050
typedef long long ll;
int n,a[N],k=30;
ll ans;
void solve(int l,int r,int d) {
if(d==-1||l>=r) return ;
if(l==r-1) {ans+=a[l]^a[r]; return ;}
int mid=l,i,j;
for(;mid<=r&&!((a[mid]>>d)&1);mid++) ;
solve(l,mid-1,d-1);
solve(mid,r,d-1);
int ls=mid-l,rs=r-mid+1;
if(ls>2&&rs>2) return ;
if(ls<1||rs<1) return ;
int mn1=1<<30,mn2=1<<30;
for(i=l;i<mid;i++) {
for(j=mid;j<=r;j++) {
int x=a[i]^a[j];
if(x<mn1) mn2=mn1,mn1=x;
else if(x<mn2) mn2=x;
}
}
if(ls<=2&&rs<=2) ans+=mn1+mn2;
else ans+=mn1;
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
int i;
for(i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
ans=0;
solve(1,n,k);
printf("%lld\n",ans);
}
}

最新文章

  1. javax.servlet.http.HttpServlet was not found
  2. 剑英陪你玩转图形学(五)focus
  3. Java中实现文件上传下载的三种解决方案
  4. PLSQL_基础系列02_分组函数GROUP BY / ROLLUP / CUBE(案例)
  5. 【LeetCode 201】Bitwise AND of Numbers Range
  6. servlet规范
  7. Java之 AtomicInteger
  8. 机器学习(1)之梯度下降(gradient descent)
  9. DMA(STM32)
  10. Java语言实现二分法
  11. rails将类常量重构到数据库对应的表中之一
  12. Doskey命令详解
  13. note_The Top Risks of Requirements Engineering
  14. 关于STM32时钟系统
  15. Globalization and accessibility for tile and toast notifications (Windows Store apps)
  16. dir for RequestHandler and request
  17. ClickOnce部署winform
  18. HDUOJ------Lovekey
  19. Java解析Json数据的两种方式
  20. iOS 关于图片地理位置隐私信息的分析和读取

热门文章

  1. 【原创】Hibernate自动生成(1)
  2. EasyDarwin开源流媒体服务器Golang版本:服务端录像功能发布
  3. Netty 源码(ChannelHandler 死磕)
  4. js网页视频播放: vcastr22 、 flowplayer 、 jwplayer
  5. 【python】-- 列表
  6. 聊聊数据库~6.SQL运维中篇
  7. IoC与DI
  8. 关于tomcate跨域配置的配置问题和表头加入新属性的过滤
  9. 《程序员代码面试指南》第二章 链表问题 将单链表每K个节点之间逆序
  10. WPF之基础概念