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

wqs二分学习笔记

一般解决问题

你有一个 \(k\),表示最后要变成 \(k\) 个,或者说是选 \(k\)

形式化地讲,设 \(f(i)\) 表示最后变成 \(i\) 个,或者是选 \(i\) 个的方案。

你一般要求的是 \(f(k)\) 的最大值或者最小值。

问题特征

你最后的 \((x,f(x))\) 是一个凸包。

而凸性意味着:如果我们给每个被选的物品增加一个相同的额外代价/收益 \(\lambda\)(称为惩罚或奖励),那么最优解中选择的物品数量 \(g(\lambda)\) 会随着 \(\lambda\) 单调变化。

为什么,这就是他的原理。

首先我们有一个凸包,然后二分它的斜率,然后就相当于平移这个直线使它的截距最大或者最小,很明显与一个点相切。

求出这个点之后可以根据 \(x\) 继续二分,因为我们求的是 \(x=k\) 的情况。

这个点为 \((x,f(x))\),那么如果我让他每次选惩罚 \(\lambda\),那么它的值就为 \(0\) 了,但是在其它的点上面,惩罚过后都是 \(\leq 0\) 的,那么我当前这个就是要找的截距最大。

于是,我们把每个 \(-\lambda\) 放进去,那么我们所求的最大的(一般用 \(dp\))便是我们要找的 \(x\),基于此二分即可。

细节

这里需要考虑一些边界情况,wqs 二分两个极端是要么只要 \(1/0\) 个,要么全都要,依据这个就行了。

而且,你还需要考虑优化的 \(dp\)\(x\) 的坐标一定要准确。

怎么判断是不是凸包呢?一种可用的方法是代价是凸函数,那么最后就是凸包,或者你可以求导解决。

例题

P4983 忘情

很好玩的题目。

题目概述

把长度为 \(n\) 的序列分成 \(k\) 个部分,每个部分的代价为 \((1+\sum_i a_i)^2\),那么最小的代价是多少呢?

分析

我们来思考一下。

我们注意到(\(\text{attention is all you need}\)),这个代价是单调的,也是凸的,所以可以用 wqs 二分解决。

最后我们求每一个少 \(\lambda\)\(dp\),显然是斜率优化即可。

代码

时间复杂度 \(\mathcal{O}(n\log V)\) 的。

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
#include <vector>
#define int long long
#define N 100005
#define sqr(x) (x) * (x)
using namespace std;
int n,m,f[N],a[N],q[N],sum[N],g[N];
double X(int id) {return sum[id];
}
double Y(int id) {return f[id] + sum[id] * sum[id] - 2 * sum[id];
}
double Slope(int fir,int sec) {return (Y(fir) - Y(sec)) / (X(fir) - X(sec));
}
void check(int mid) {memset(f,0x3f,sizeof f),memset(g,0,sizeof g);f[0] = 0;int head = 1,tail = 0;q[++tail] = 0;for (int i = 1;i <= n;i ++) {while(head < tail && Slope(q[head],q[head + 1]) < 2 * sum[i]) head ++;f[i] = f[q[head]] + sqr(sum[i] - sum[q[head]] + 1) + mid;g[i] = g[q[head]] + 1;while(head < tail && Slope(q[tail - 1],q[tail]) > Slope(q[tail],i)) tail --;q[++tail] = i;}
}
signed main(){cin >> n >> m;for (int i = 1;i <= n;i ++) {scanf("%lld",&a[i]);sum[i] = sum[i - 1] + a[i];}int l = 0,r = 1e18,res = 0;while (l <= r) {int mid = l + r >> 1;check(mid);if (g[n] <= m) r = mid - 1,res = mid;//x坐标不在要求的右边,那么我们求的x坐标要尽量靠左,因为如果你算的尽量靠右的话,有可能会被判掉else l = mid + 1;}check(res);cout << f[n] - m * res;return 0;
}

P2619 [国家集训队] Tree I

题目概述

给你一个带权无向连通图(有白边和黑边),恰好用 \(k\) 条白边的最小生成树。

分析

你可以通过打表或者怎么发现:一开始我限制了 \(\leq i\) 条白边,那么对于原本的最小生成树的白边数量 \(p\),如果 \(i\leq p\),那么单调下降,因为有些白边原本就可以替代一些黑边;如果 \(i> p\),那么单调上升,因为有些更优的黑边被你的白边给替代了。

于是我们就能通过此题了。

代码

时间复杂度 \(\mathcal{O}(n\log n\log V)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#define int long long
#define N 100005
using namespace std;
int n,m,k;
struct node{int u,v,w,col;
}a[N],b[N];
int fa[N];
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int tj,ans;
void check(int mid) {tj = 0;ans = 0;for (int i = 1;i <= m;i ++) b[i] = a[i];for (int i = 1;i <= m;i ++)if (b[i].col == 0) b[i].w += mid;//更难被选到stable_sort(b + 1,b + 1 + m,[](node x,node y) {if (x.w == y.w) return x.col > y.col;//尽量少用return x.w < y.w;});for (int i = 1;i <= n;i ++) fa[i] = i;for (int i = 1;i <= m;i ++) {int x = b[i].u,y = b[i].v;int xx = find(x),yy = find(y);if (xx != yy) fa[xx] = fa[yy],tj += (b[i].col == 0),ans += b[i].w;}
}
signed main(){cin >> n >> m >> k;int cnt = 0;for (int i = 1;i <= m;i ++) {int u,v,col,w;scanf("%lld%lld%lld%lld",&u,&v,&w,&col);a[i] = {u + 1,v + 1,w,col};cnt += (col == 0);}// for (int i = 0;i <= cnt;i ++) {//     for (int j = 1;j <= n;j ++) fa[j] = j;//     int choose = 0,ans = 0;//     for (int j = 1;j <= m;j ++) {//         int x = a[i].u,y = a[i].v;//         int xx = find(x),yy = find(y);//         if (xx != yy) {//             if ((a[i].col == 0 && choose < i) || a[i].col == 1) fa[xx] = fa[yy],cnt += a[i].col == 0,ans += a[i].w;//         }//     }//     printf("%lld %lld\n",i,ans);// }// 从小到大,能用就用白的,但是不能超过限制,所以说前面的代价都是单调下降,到了极点,也就是原本最小生成树的白边个数后,它不得不用更大的白边去替换小的黑边,所以单调上升这是一个凸函数int l = -1e18,r = 1e18,res = -1e18;while(l <= r) {int mid = l + r >> 1;check(mid);if (tj <= k) r = mid - 1,res = mid;else l = mid + 1; }// cout << res << '\n';check(res);cout << ans - k * res;return 0;
}

如果说你最后减去的是 \(tj\times res\),那么你是错的,因为这里我是优先选择了白边的,所以会导致 \(tj\leq k\),使得答案更大。

先暂时更新到这里

http://www.hskmm.com/?act=detail&tid=29891

相关文章:

  • Android系统中使用initrc脚本在开机时禁用selinux
  • 2025年10月氧化镁厂家最新推荐排行榜,轻烧氧化镁,重烧氧化镁,高纯氧化镁,活性氧化镁公司推荐!
  • Vector向量数据库对比
  • 2025 年最新推荐集装箱拖车供应厂家权威榜单:全方位解析优质企业实力,助力精准选择箱式 / 冷藏等拖车服务
  • 2025 年试验箱厂家最新推荐排行榜:聚焦高低温 / 恒温恒湿 / 冷热冲击等设备研发实力与 ISO 质量管控的标杆企业精选
  • 完整教程:PyTorch深度学习实战【12】之基于RNN的自然语言处理入门
  • IDA9.0中文版与相关插件安装详细教程
  • 2025 北京宽带安装公司最新推荐榜:专业口碑双优服务商汇总,企业家庭装机必看指南北京企业/北京无线/北京商务/北京商业/北京店铺宽带安装公司推荐
  • 2025年10月苹果仓源头厂家最新推荐榜单:专业仓储与高效配送的优质选择!
  • 2025年10月整平机厂家最新推荐排行榜,精密整平机,自动整平机,金属板材整平机公司推荐!
  • 2025 最新铝型材源头厂家推荐排行榜:优选企业深度解析,佛山龙头与新锐品牌选购指南
  • linux与window文件互传方式
  • 行业推荐:广州智建云工程管理软件/软件系统/软件App/软件平台/工程管理软件和验房系统公司获认可,专业方案成品质管控优选
  • 2025 聚合氯化铝厂家最新推荐榜:优质厂家选购指南与高口碑品牌全解析聚合氯化铝絮凝剂/水处理用聚合氯化铝/生产聚合氯化铝厂家推荐
  • 2025 年最新推荐!防水堵漏工程公司权威榜单重磅发布,覆盖地下室 / 污水池 / 伸缩缝等场景,帮业主避开乱象选靠谱企业
  • 2025 年最新留学机构权威最新推荐排行榜,深度解析顶尖机构服务特色与核心优势助力留学规划英国/澳洲/香港/美国/加拿大留学机构推荐
  • 2025 药包材辅导公司最新推荐榜:含 GMP 验证 / 质量管理体系 / 实验室装修等服务优质机构盘点公司推荐
  • 2025年10月氢氧化镁厂家最新推荐排行榜,阻燃剂氢氧化镁,环保型氢氧化镁,高纯度氢氧化镁公司推荐!
  • 2025年10月通风气楼厂家权威推荐:专业通风解决方案优选榜单
  • 多进程环境中解决 PHP 文件系统锁定问题指南
  • 2025年10月瑕疵检测设备厂家最新推荐排行榜,表面/薄膜/铝箔/陶瓷膜瑕疵在线检测,外观瑕疵检测机/仪公司推荐!
  • 2025年10月南通市婚纱摄影最新推荐榜单:创意拍摄与优质服务完美结合!
  • mysql数据库定时执行sql语句
  • 2025 年打包机厂家最新推荐排行榜:螺丝 / 五金 / 称重 / 半自动 / 全自动打包机优选企业榜单
  • 基于MATLAB的ADS-B接收机卫星与接收天线初始化实现
  • SpringBoot中这10个神仙功能,惊艳到我了!
  • 智能小e-外联系统文档 - 教程
  • 2025 年最新推荐!路灯厂家权威榜单:涵盖太阳能、高杆、LED 道、景观、庭院灯,助力采购方精准选优质品牌
  • 2025 年同声传译 APP 推荐!翻译鸥:AI 智能同传、视频 / 图片翻译工具,跨语言沟通实用之选
  • 学习科学的笔记