洛谷题目传送门

给一个比较有逼格的名词——WQS二分/带权二分/DP凸优化(当然这题不是DP)。

用来解决一种特定类型的问题:

有\(n\)个物品,选择每一个都会有相应的权值,需要求出强制选\(need\)个物品时的最大/最小权值和。

一般来说,我们求不限制个数的最大/最小权值和很容易,但在限制个数的前提下再求最值会变得有点困难。比较低效的做法是对状态再加设一个维度表示已选物品数量,然后通过DP等方法求出。

应用前提:设\(g_x\)为强制选\(x\)个物品的最大/最小权值和,如果所有的点对\((x,g_x)\)在平面上能够构成一个凸包,那么可以考虑使用WQS二分。

所以说用三个名词合指它也不为过(提出者WQS,二分的量是权值增量,使用前提是凸函数)

WQS的论文这里可以下载

建议食用Creeper_LKF大佬的blog,数形结合的分析过程已经非常完整了。

简单的来说,我们不能知道这个凸包长什么样子,但我们可以拿着一个斜率为\(k\)的直线去切这个凸包,相当于给每个物品附加了一个权值\(k\)。设直线的截距为\(b\),那么选\(x\)个物品后总权值就会等于\(b+kx\)。我们通过\(O(n)\)的DP等方法找到最大的\(b\),同时也可以求出选了的个数\(x\),通过\(x\)与\(need\)的关系来调整直线斜率继续二分。

拿本题来说,选\(x\)条白边,可以写个平方DP然后发现\(g_x\)是个下凸函数。然后我们在\([-100,100]\)(显然是斜率的上下界,因为更改一条边带来的权值和的更改不会超过\(100\))的范围内二分\(k\),之后所有白边的权值增加\(k\),跑一遍Kruscal统计选了多少条白边。如果这个数量大于等于\(need\)就调大\(k\),否则调小。

最后斜率为\(mid\)的直线与凸包的切点就是答案,注意从中减去\(k\)的影响(ans-=mid*x

边界问题Creeper_LKF大佬也证明了只要在边权相等的时候优先选白边就没问题了。

写法上有一个优化:每次Kruscal的时候不用重新排序了。因为每次我们只是给所有白边整体加一个权值,所以如果我们先把白边和黑边分开排序的话,加完以后也还是有序的。每次Kruscal时只要用类似归并排序的方法\(O(E)\)的扫一遍就可以啦!复杂度从\(O(E\log E\log 200)\)降到了\(O(E\log E+E\log200)\),目前暂时rank1,欢迎超越。

#include<cstdio>
#include<algorithm>
#define RG register
#define R RG int
#define G if(++ip==iend&&fread(ip=buf,1,N,stdin))
using namespace std;
const int N=5e5+9,M=1e6+9;
char buf[N],*iend=buf+N,*ip=iend-1;
inline int in(){
while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x=x*10+(*ip&15);G;}
return x;
}
struct Edge{
int u,v,w;bool c;
inline bool operator<(RG Edge&x){
return w<x.w;
}
}e[M];
int f[N];
int getf(R x){
return x==f[x]?x:f[x]=getf(f[x]);
}
inline bool add(R i){//尝试加边并返回是否成功
if(getf(e[i].u)==getf(e[i].v))return 0;
f[f[e[i].u]]=f[e[i].v];return 1;
}
int main(){
R n=in(),mw=0,m=in(),need=in(),i,j;//mw为白边数量
for(i=0;i<m;++i){//点和边都从0开始存了
e[i].u=in();e[i].v=in();e[i].w=in();
if(!(e[i].c=in()))swap(e[mw++],e[i]);//将黑白边分开
}
sort(e,e+mw);sort(e+mw,e+m);
R l=-100,r=100,mid,ans;
while(l<r){
mid=(l+r+1)>>1;
for(i=0;i<n;++i)f[i]=i;
ans=i=0;j=mw;
while(i<mw&&j<m)//类归并排序
e[i].w+mid<=e[j].w?ans+=add(i++):add(j++);
while(i<mw)ans+=add(i++);//白边数量统计完整
ans<need?r=mid-1:l=mid;
}
mid=l;
for(i=0;i<n;++i)f[i]=i;
ans=i=0;j=mw;//最后算权值总和
while(i<mw&&j<m)
if(e[i].w+mid<=e[j].w)
ans+=(e[i].w+mid)*add(i),++i;
else ans+=e[j].w*add(j),++j;
while(i<mw)ans+=(e[i].w+mid)*add(i),++i;
while(j<m )ans+=e[j].w*add(j),++j;
printf("%d\n",ans-need*mid);//减掉
return 0;
}

洛谷P2619 [国家集训队2]Tree I(带权二分,Kruscal,归并排序)的更多相关文章

  1. 洛谷.2619.[国家集训队2]Tree I(带权二分 Kruskal)

    题目链接 \(Description\) 给定一个无向带权连通图,每条边是黑色或白色.求一棵最小权的恰好有K条白边的生成树. \(Solution\) Kruskal是选取最小的n-1条边.而白边数有 ...

  2. P2619 [国家集训队2]Tree I(最小生成树+二分)

    P2619 [国家集训队2]Tree I 每次二分一个$x$,每条白边加上$x$,跑最小生成树 统计一下满足条件的最小值就好了. to me:注意二分不要写挂 #include<iostream ...

  3. luogu P2619 [国家集训队2]Tree I

    题目链接 luogu P2619 [国家集训队2]Tree I 题解 普通思路就不说了二分增量,生成树check 说一下坑点 二分时,若黑白边权有相同,因为权值相同优先选白边,若在最有增量时出现黑白等 ...

  4. Luogu P2619 [国家集训队2]Tree I(WQS二分+最小生成树)

    P2619 [国家集训队2]Tree I 题意 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有\(need\)条白色边的生成树. 题目保证有解. 输入输出格式 输入格式 ...

  5. 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)

    洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...

  6. 洛谷 P1501 [国家集训队]Tree II 解题报告

    P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...

  7. 洛谷P1501 [国家集训队]Tree II(LCT,Splay)

    洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...

  8. [洛谷P1527] [国家集训队]矩阵乘法

    洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...

  9. 洛谷 P1505 [国家集训队]旅游 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1505 [国家集训队]旅游 题目描述 Ray 乐 ...

随机推荐

  1. Lean Data Innovation Sharing Salon(2018.09.15)

    时间:2018.09.15地点:北京国华投资大厦

  2. mysql利用binlog进行数据恢复

    目录 mysql利用binlog进行数据恢复 binlog基本配置和格式 binlog基本配置 查看binlog状态 binlog的三种格式 转换成sql mysql自带的mysqlbinlog 利用 ...

  3. 将WinForm程序(含多个非托管Dll)合并成一个exe的方法

    原文:将WinForm程序(含多个非托管Dll)合并成一个exe的方法 开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了. ILMerge能把托管dl ...

  4. 基于uFUN开发板的心率计(三)Qt上位机的实现

    前言 上两周利用周末的时间,分别写了基于uFUN开发板的心率计(一)DMA方式获取传感器数据和基于uFUN开发板的心率计(二)动态阈值算法获取心率值,介绍了AD采集传感器数据和数据的滤波处理获取心率值 ...

  5. 使用Hexo+Github搭建属于自己的博客(进阶)

    主题的配置:这里以NexT主题作为题材 1.安装NexT,在其文件夹中鼠标右键,点击Git Base Here.输入命令:git clone https://github.com/iissnan/he ...

  6. 【nodejs】让nodejs像后端mvc框架(asp.net mvc )一样处理请求--控制器的声明定义和发现篇(3/8)

    文章目录 前情概要 前面文章把路由已经介绍的差不多了,包括url映射,路由选择等.接下来讲一讲controller的一些基本规则 BaseController的所有代码都在这里拉.相当简单. 主要逻辑 ...

  7. .NETCore_初探

    1. Core默认的服务注册 Statup文件(rogram类型中创建 WebHost时使用的)中有俩个方法: Configure和ConfigureServices(将服务放置到容器里面) publ ...

  8. StoryLine3变量存储与跳转后台时的使用

    前言 公司项目原因,接触到storyline3(后面简称SL)课件制作工具,类似ppt,但是又多了互动.交互,且页面元素可添加触发器,触发器中可执行js代码. 1.官方教程 在SL中,会有“了解详情. ...

  9. Linux下selinux简单梳理

    在linux环境下执行某些程序时,偶尔会遇到来一个关于selinux的强制模式不可执行的情况,这种情况下需要关闭selinux或者将enforcing改为permissive模式后才能进行执行.sel ...

  10. 第三次作业 (一)----------------------Visual Studio 2015的安装及单元测试

    这是第三周的第一个作业,Visual Studio 2015的安装及单元测试. 我的电脑之前安装过Visual Studio 2015,但是在安装过程中我从来没有留意过各种注意事项,所集正好借此作业的 ...