链接

PDF

bzoj

先求出正置边和反置边时b+1到前b个点的最短路dis[0/1][x](x∈[1,b]),

令D[x]=dis[0][x]+dis[1][x]

然后分组后每个x对代价的贡献为D[x]*(所在组中元素个数-1)

考虑DP决策分组过程,发现没有一个很好的序,

不过为了使得代价小,应该把D小的放在个数大的组里,D大的放在个数少的组里

由此可以想出,应该是大小相近的元素放在了同一组中,这意味着,先排序,在划分成s段,的所有情况包含了原问题的最优解

于是把D[1~b]排序后,有方程

$f[i][j]=MIN_{k=0}^{j-1}[f[i-1][k]+(j-k-1)*(sum[j]-sum[k])]$

$O(n^3)$

其中:f[i][j]表示把前j个分成i组的最小值,sum为D的前缀和

非法状态均置为INF

由于可以粗略的知道这个东西在j确定,i为自变量的函数图像上有凸性

(可以玄学地认为,最开始的时候,多划分一刀可以造成很大的改变,随着划分次数越来越多,多划分一刀的改变越来越微小)

于是,可以使用带权二分来优化这一DP

即,消去对划分次数的限制,通过二分来找到一个合适的划分附加代价,使得即使不限制划分次数,最后的最优解也恰好满足我们对划分数的限制

这样有了一个新的方程

$f'[j]=MIN_{k=0}^{j-1}[f'[k]+(j-k-1)*(sum[j]-sum[k])]+C$

$O(n^2log)$

考虑优化转移过程

拆开方程得到

$f'[j]=MIN_{k=0}^{j-1}[f'[k]+(k+1)sum[k]-ksum[j]-jsum[k]]+(j-1)sum[j]+C$

在方程中

当固定j不动时

随k增加,f'[k]+(k+1)sum[k]项增加,-ksum[j]-jsum[k]项减小

而随j的增加,含j的项(即-ksum[j]-jsum[k])对答案的影响加剧,于是,随j的增加,j的最优决策中的k会单调变大(随j的增加,我们决策时更为看重含j项,为了使含j项减小,我们试图使用更大的k)

这意味着这个方程有决策单调性

本题通过带权二分和决策单调性优化可以做到$O(nlog^2)$

(感觉最近状态很差,午休一直睡不着来着,几个月了吧,先是用N^2log给方哥号上贡献了半屏T,又以为可以nlog做,然后贡献了半屏Wa,最后才发现决策单调性)

代码:

 #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define P pair <int ,int >
using namespace std;
priority_queue <P ,vector <P > ,greater <P > > PQ ;
int n,b,s,r;
struct INP{
int u,v,val;
}inp[];
struct ss{
int to,next,val;
}e[];
int first[],num;
LL d[],f[],sum[];
int lin[],dis[],que[],grt_st[];
void build(int ,int ,int );
void dij(int );
bool check(LL );
LL ask(int ,int );
int main()
{
int i,j,k,l;
LL L,R,mid;
scanf("%d%d%d%d",&n,&b,&s,&r);
for(i=;i<=r;i++){
scanf("%d%d%d",&inp[i].u,&inp[i].v,&inp[i].val);
build(inp[i].u,inp[i].v,inp[i].val);
}
dij(b+);
for(i=;i<=b;i++) d[i]=dis[i];
memset(first,,sizeof(first)),num=;
for(i=;i<=r;i++)
build(inp[i].v,inp[i].u,inp[i].val);
dij(b+);
for(i=;i<=b;i++) d[i]+=dis[i];
sort(d+,d+b+);
for(i=;i<=b;i++) sum[i]=sum[i-]+d[i];
L=,R=b*sum[b],mid=(L+R)>>;
while(R-L>=){
if(check(mid)) L=mid;
else R=mid-;
mid=(L+R)>>;
}
for(mid=R;mid>=L;mid--)
if(check(mid)){
printf("%lld\n",f[b]-s*mid);
return ;
}
return ;
}
void build(int f,int t,int val){
e[++num].next=first[f];
e[num].to=t,e[num].val=val;
first[f]=num;
}
void dij(int S){
int i,U;
memset(dis,0x3f,sizeof(dis));
dis[S]=;
P u,v;
u.first=,u.second=S;
PQ.push(u);
while(!PQ.empty()){
u=PQ.top();
PQ.pop();
U=u.second;
for(i=first[U];i;i=e[i].next)
if(dis[e[i].to]>dis[U]+e[i].val){
dis[e[i].to]=dis[U]+e[i].val;
v.first=dis[e[i].to],v.second=e[i].to;
PQ.push(v);
}
}
}
bool check(LL lim){
int tmp=,i,h=,t=;
int l,r,mid;
f[]=lin[]=,grt_st[]=;
que[t]=;
for(i=;i<=b;i++){
l=h+,r=t,mid=(l+r)>>;
while(r-l>){
if(i>=grt_st[que[mid]]) l=mid;
else r=mid-;
mid=(l+r)>>;
}
for(mid=r;mid>=l;mid--)
if(i>=grt_st[que[mid]]){
f[i]=ask(i,que[mid])+lim,lin[i]=lin[que[mid]]+;
break;
}
if(i==b) break;
grt_st[i]=b+;
while(h<t&&grt_st[que[t]]>i&&ask(grt_st[que[t]],i)<=ask(grt_st[que[t]],que[t])) grt_st[i]=grt_st[que[t]],t--;
if(h<t){
l=max(grt_st[que[t]],i+),r=grt_st[i]-,mid=(l+r)>>;
while(r-l>){
if(ask(mid,i)<=ask(mid,que[t])) r=mid;
else l=mid+;
mid=(l+r)>>;
}
for(mid=l;mid<=r;mid++)
if(ask(mid,i)<=ask(mid,que[t])){
grt_st[i]=mid;
break;
}
}
if(grt_st[i]!=b+)
que[++t]=i;
}
return lin[b]>=s;
}
LL ask(int x,int typ){
return f[typ]+(x-typ-)*(sum[x]-sum[typ]);
}

[World Final 2016] Branch Assignment的更多相关文章

  1. 4609: [Wf2016]Branch Assignment 最短路 DP (阅读理解题)

    Bzoj的翻译出锅了所以来官方题面:这个题应该是单向边而BZOJ说的是双向边,什么你WA了?谁叫你懒得看英文...... 显然我们能正向反向两遍SPFA处理出每个点到总部的距离和总部到每个点的距离.如 ...

  2. Gym-101242B:Branch Assignment(最短路,四边形不等式优化DP)

    题意:要完成一个由s个子项目组成的项目,给b(b>=s)个部门分配,从而把b个部门分成s个组.分组完成后,每一组的任 意两个点之间都要传递信息.假设在(i,j)两个点间传送信息,要先把信息加密, ...

  3. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  4. BZOJ 4619 Swap Space 解题报告

    今天是因为David Lee正好讲这个题的类似题,我才做了一下. 本题是world final 2016的一道水…… 题目地址如下 http://www.lydsy.com/JudgeOnline/p ...

  5. Kafka Consumer2

    本文记录了和conumser相关的几个类. 首先是RequestFuture这个类,consumer和服务端通信使用它作为返回值. 其次是HeartBeat机制,consumer和coordinato ...

  6. JGit----将 Git 嵌入你的应用

    如果你想在一个 Java 程序中使用 Git ,有一个功能齐全的 Git 库,那就是 JGit . JGit 是一个用 Java 写成的功能相对健全的 Git 的实现,它在 Java 社区中被广泛使用 ...

  7. 2016/09/21 Java关键字final

    1.final类 final类不能被继承,没有子类,final类中的方法默认是final的. final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的. 2.final方 ...

  8. 2016 China Collegiate Programming Contest Final

    2016 China Collegiate Programming Contest Final Table of Contents 2016 China Collegiate Programming ...

  9. Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution

    Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution 题目链接:https://atcoder.jp/contests/cf16- ...

随机推荐

  1. cAdvisor+InfluxDB+Grafana 监控Docker

    容器的监控方案其实有很多,有docker自身的docker stats命令.有Scout.有Data Dog等等,本文主要和大家分享一下比较经典的容器开源监控方案组合:cAdvisor+InfluxD ...

  2. Docker仓库(四)

    一.什么是仓库 仓库就是集中存放镜像的地方,分为公共仓库和私有仓库,一个容易混淆的概念是注册服务器,实际上注册服务器是存放仓库的具体服务器,一个注册服务器可以有多个仓库,而每个仓库下面有多个镜像 二. ...

  3. dubbo管控台安装

    1. jdk安装 #  cp installpkgs/jdk-7u67-linux-x64_tar_gz /usr/local #  tar -zxf jdk-7u67-linux-x64_tar_g ...

  4. gradle构建工具

    在使用android studio开发android程序时,as就是基于gradle进行构建的,我们只需要通过run就可以编译.打包.安装,非常方便,但是究竟gradle是什么呢?  一.java构建 ...

  5. 小程序/js监听输入框验证金额

    refundAmoutInput: function(event){ var value = event.detail.value; if (value.split('.')[0].length &g ...

  6. Android 开发工具类 36_ getSimSerial

    1 /** * 获取手机的 sim 卡串号 * 需要在清单文件中配置权限: * <uses-permission android:name="android.permission.RE ...

  7. 全网最详细的HA集群的主节点之间的双active,双standby,active和standby之间切换的解决办法(图文详解)

    不多说,直接上干货! 1. HA集群的主节点之间的双standby的解决办法: 全网最详细的Hadoop HA集群启动后,两个namenode都是standby的解决办法(图文详解) 2. HA集群的 ...

  8. es-07-head插件-ik分词器插件

    5.x以后, es对head插件的支持并不是特别好 而且kibana的功能越来越强大, 建议使用kibana 1, head插件安装 在一台机器上安装head插件就可以了 1), 更新,安装依赖 su ...

  9. Windows下编译打包Spice PC客户端

    目录 1 环境搭建 2 编译客户端 3 打包客户端   1 环境搭建 1.1 准备工作 安装启动: 安装替换图标工具: Resource Hacker 安装exe制作工具: NSIS(提取码:3dfp ...

  10. mysql 查找在另一张表不存在的数据

    有两个表Phone_book, Call: Phone_book +----+------+--------------+ | id | name | phone_number | +----+--- ...