当前位置: 首页 > news >正文

CF1626D 题解

CF1626D 题解

貌似题解区没有这种解法。

题面

CF1626D Martial Arts Tournament - 洛谷 (luogu.com.cn)

思路

问题就是把 \(a\) 分成 \(3\) 个子集(可以为空),每两个子集里的数并不重复,把每个子集的大小补到 \(2^x\) 最少要补的数的个数。

先把 \(a\) 给排序,那么就可以转化为给 \(a\) 选择两个满足 \(a_i\neq a_{i+1}\)\(i\) 后面切两刀(\(i\) 可以相同),分成 \(3\) 段,求把 \(3\) 段补成 \(2^x\) 最少要补的数的个数。

考虑二分答案,然后判断是否可以只用补小于等于 \(mid\) 的个数的数。

考虑枚举第一个断点,然后枚举第二段的长度,这里我们贪心地选择 \(2^x,x\in\mathbb{Z}\),但是这个点不一定能作为断点,则我们就要把这个点左边第一个能断的点作为第二个断点、以及右边第一个能断的点作为第二个断点的答案都给算上,遇到小于等于 \(mid\) 的直接返回,注意判边界。

时间复杂度 \(O(n\log^2n)\)

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #define gc getchar
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#define FILE(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
#define FIN(s) freopen(s".in","r",stdin);
#define FOUT(s) freopen(s".out","w",stdout);
#define ll long long
#define re register int
#define rl register ll
#define il inline
using namespace std;
const int MN=2e5+5;
ll n,a[MN],l[MN],r[MN];
char buf[1<<23],*p1=buf,*p2=buf;
il void write(rl n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
il ll read(){ll x=0,f=1;char ch=gc();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}return x*f;}
il ll gs(rl x){if(!x)return 1;if((1<<__lg(x))==x)return 0;return (1<<__lg(x)+1)-x;}
il bool check(rl num){for(re i=1; i<=n; ++i) if(a[i]!=a[i+1]||i==n){if(gs(i)+gs(n-i)+1<=num) return true;for(re j=0; i+(1<<j)+1<=n; ++j){ll L=l[i+(1<<j)+1],R=r[i+(1<<j)+1]-1;if(L<=i) continue;if(gs(i)+gs(L-i)+gs(n-L)<=num) return true;if(R>n) continue;if(gs(i)+gs(R-i)+gs(n-R)<=num) return true;}}return false;
}
il void solve(){n=read();for(re i=1; i<=n; ++i) a[i]=read();sort(a+1,a+1+n);for(re i=1; i<=n; ++i) if(a[i]!=a[i-1]||i==1) l[i]=i-1;else l[i]=l[i-1];for(re i=n; i; --i) if(a[i]!=a[i+1]||i==n) r[i]=i+1;else r[i]=r[i+1];ll l=0,r=gs(n)+2;while(l<r){ll mid=l+r>>1;if(check(mid)) r=mid;else l=mid+1;}write(l);putchar('\n');
}
int main(){// ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);ll T=read();while(T--)solve();return 0;
}//250915
http://www.wxhsa.cn/company.asp?id=5157

相关文章:

  • Python 集合运算:并集、交集、差集全解析
  • 第一周数据可视化作业
  • 用 C++ + OpenCV + Tesseract 实现英文数字验证码识别
  • java 第一节课课前提问
  • 二进制解码器、选通器和分配器
  • 2025最新版 Photoshop软件免费下载安装完整教程(PS2025)超详细安装教程
  • nac一键卸载软件脚本
  • 交叉编译openharmony版本的openssh
  • 为什么不建议在 Docker 中跑 MySQL
  • CFD
  • [MCP][05]Elicitation示例
  • Warsaw主题关闭导航条
  • Python Socket网络编程(2)
  • PS2025安装包下载及PS2025安装包安装教程详细步骤(包含安装包下载链接)
  • Nature Genetics | 本周最新文献速递
  • 关于go里切片作为函数参数时是引用传递还是值传递
  • DRAN读写循环
  • 数据结构操作相关
  • Neisbitt 不等式的证法
  • 端口转发神器Rinetd:轻量级安装与配置指南
  • C语言中递归思想的应用
  • WITH RECURSIVE 递归公用表表达式(CTE)
  • leetcode 3541. 找到频率最高的元音和辅音 便捷
  • 匿名递归与不动点组合子
  • Markdown学习Day01
  • flutter compass结构代码分析
  • 25.9.15
  • 二十八、共享内存多处理器的基本概念
  • 详细介绍:【ARMv7】系统复位上电后的程序执行过程
  • C#高级语法