因为两个人方案的对称性,可以将$k$除以$2$,转化为在$n-1$个间隔中设置若干断点,求第$k$小的增量。

对于选中的相邻的断点$(a,a+1)$和$(b,b+1)$,增量为$|x_a-x_{b+1}|$。

将绝对值拆开,用可持久化权值线段树优化建图,然后求$k$短路即可。

时间复杂度$O(n\log^2n+k\log k)$。

#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<ll,int>P;
const int MAXN=10010,N=400000,M=2000000;
const ll inf=1LL<<60;
int n,K,i,a[MAXN],b[MAXN],T0,T1,l[N],r[N],tot;ll base,ans;
namespace G{
int n,m,i,S,T,g[N],v[M],u[M],w[M],nxt[M],f[N],h[N],tot;ll d[N];bool is[M],vis[N];
struct Node{
int l,r,d;P v;
Node(){}
Node(int _l,int _r,int _d,P _v){l=_l,r=_r,d=_d,v=_v;}
}pool[M*4];
inline int build(P v){
pool[++tot]=Node(0,0,0,v);
return tot;
}
int merge(int a,int b){
if(!a||!b)return a+b;
if(pool[a].v>pool[b].v)swap(a,b);
int x=++tot;
pool[x]=pool[a];
pool[x].r=merge(pool[a].r,b);
if(pool[pool[x].l].d<pool[pool[x].r].d)swap(pool[x].l,pool[x].r);
pool[x].d=pool[x].r?pool[pool[x].r].d+1:0;
return x;
}
void cal(int x){
if(vis[x])return;
vis[x]=1;
d[x]=inf,f[x]=0;
if(x==T){d[x]=0;return;}
for(int i=g[x];i;i=nxt[i]){
cal(u[i]);
if(d[u[i]]+w[i]<d[x])d[x]=d[u[i]]+w[i],f[x]=i;
}
}
void dfs(int x){
if(!f[x]||vis[x])return;
vis[x]=1;
dfs(u[f[x]]);
h[x]=merge(h[x],h[u[f[x]]]);
}
inline void add(int x,int y,int z){
if(!x||!y)return;
v[++m]=x;u[m]=y;w[m]=z;nxt[m]=g[x];g[x]=m;
}
void solve(){
for(i=1;i<=n;i++)cal(i);
ans=d[S];
if(K==1)return;
K--;
for(i=1;i<=n;i++)vis[i]=0,is[f[i]]=1;
for(i=1;i<=m;i++)if(!is[i]&&d[u[i]]<inf)h[v[i]]=merge(h[v[i]],build(P(w[i]-d[v[i]]+d[u[i]],u[i])));
for(i=1;i<=n;i++)dfs(i);
priority_queue<P,vector<P>,greater<P> >q;
ll x,y;
y=h[S];
if(y)q.push(P(d[S]+pool[y].v.first,y));
while(!q.empty()&&K){
K--;
P t=q.top();q.pop();
ans=t.first;
x=t.second,y=pool[x].l;
if(y)q.push(P(ans-pool[x].v.first+pool[y].v.first,y));
y=pool[x].r;
if(y)q.push(P(ans-pool[x].v.first+pool[y].v.first,y));
y=h[pool[x].v.second];
if(y)q.push(P(ans+pool[y].v.first,y));
}
}
}
int ins(int x,int a,int b,int c,int X,int W){
int y=++tot;
if(a==b){
G::add(X,y,W);
return y;
}
int mid=(a+b)>>1;
if(c<=mid)l[y]=ins(l[x],a,mid,c,X,W),r[y]=r[x];
else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c,X,W);
G::add(l[y],y,0),G::add(r[y],y,0);
return y;
}
void ask(int x,int a,int b,int c,int d,int X,int W){
if(!x)return;
if(c<=a&&b<=d){
G::add(x,X,W);
return;
}
int mid=(a+b)>>1;
if(c<=mid)ask(l[x],a,mid,c,d,X,W);
if(d>mid)ask(r[x],mid+1,b,c,d,X,W);
}
int main(){
scanf("%d%d",&n,&K);
K=(K+1)/2;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
base+=abs(a[i]-a[i-1]);
}
sort(b,b+n+1);
for(i=0;i<=n;i++)a[i]=lower_bound(b,b+n+1,a[i])-b;
G::S=1;
G::T=2;
tot=2;
G::add(1,2,0);
for(i=1;i<n;i++){
int x=++tot,w=-abs(b[a[i]]-b[a[i+1]]);
G::add(1,x,w+abs(b[a[i+1]]));
G::add(x,2,0);
ask(T0,0,n,0,a[i+1],x,w+b[a[i+1]]);
if(a[i+1]<n)ask(T1,0,n,a[i+1]+1,n,x,w-b[a[i+1]]);
T0=ins(T0,0,n,a[i],x,-b[a[i]]);
T1=ins(T1,0,n,a[i],x,b[a[i]]);
}
G::n=tot;
G::solve();
return printf("%lld",ans+base),0;
}

  

BZOJ3945 : 无聊的邮递员的更多相关文章

  1. 无聊的 邮递员 插头dp

    邮递员想知道,如果他每天都用不同路线走过10×20个点阵邮筒,他必须活过多少个世纪才能走遍所有方案? 7:00 改完T1,开始肝插头dp 7:10 放弃,颓博客 7:20 学习插头dp 7:21 放弃 ...

  2. bzoj AC倒序

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

  3. 无聊的人用JS实现了一个简单的打地鼠游戏

    直入正题,用JS实现一个简单的打地鼠游戏 因为功能比较简单就直接裸奔JS了,先看看效果图,或者 在线玩玩 吧 如果点击颜色比较深的那个(俗称坏老鼠),将扣分50:如果点击颜色比较浅的那个(俗称好老鼠) ...

  4. [无聊的事-连载之连开100个VS] 折腾你的骚机吧,骚年们!!!

    [无聊的事-连载之连开100个VS] 折腾你的骚机吧,骚年们!!! 只有8G内存的,用这个:打开你的CMD命令提示符如果只装了Visual Studio 2010,用这条命令,打开50个VSfor / ...

  5. 一个无聊的python + opencv 示例

    opencv不用多说,先推荐一个给力的教程: https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_tutor ...

  6. Python无聊的总结

    在公司无聊的时候看了前辈写的python代码,突然发现一个比较好玩的python表达式: lambda x,y:x+y 咋一看,这个应该类似方法之类的,上网查了查,所以特此总结下 lambda:上代码 ...

  7. Python的高级特性10:无聊的@property

    @property装饰器其实有点无聊,单独拿出来作为一个知识点其实没必要,尽管它可以将方法变成属性,让get和set方法更好用,但是,它破坏了python的简洁(不是代码的简洁而是指语法上). 下面来 ...

  8. 洛谷P1629 邮递员送信

    题目描述 有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间.这个邮递员每 ...

  9. 暑假热身 E. 无聊的LSY

    LSY大牛没事就爱玩游戏,包括很多很无聊的游戏.某日,LSY大牛又找到了一个无聊的游戏:每一局游戏的开始,LSY大牛将代表自己的棋子放在一个线性棋盘的最左端(第0个格子,可以认为向右端无限延伸),接着 ...

随机推荐

  1. String 类的实现(1)浅拷贝存在的问题以及深拷贝实现

    1.   浅拷贝 : 也称位拷贝 , 编译器只是直接将指针的值拷贝过来, 结果多个对象共用 同 一块内存, 当一个对象将这块内 存释放掉之后, 另 一些对象不知道该块空间已经还给了系统, 以为还有效, ...

  2. 饮冰三年-人工智能-linux-07 硬盘分区、格式化及文件系统的管理

    先给虚拟机添加一个硬盘 通过fdisk -l sdb,查看磁盘内容 通过fdisk /sdb 来操作分区 创建一个新分区 创建第二个分区 创建第三个分区 创建扩展分区 再次创建分区,其实使用的是扩展分 ...

  3. python 0007

    #coding='utf-8'# import re import os def get_list(): list_file=[] for f in os.listdir(): if f.endswi ...

  4. C#学习-静态

    有提过类的成员,有字段.属性.方法和构造函数等,也可以使用static关键字将其声明为类的静态成员. 静态成员属于类级别的概念,它不属于类的实例. 可以使用static关键字来声明静态字段,静态字段与 ...

  5. CAS5.3.X 配置备忘

    ## # 普通MD5用户jdbc验证 ## #配置数据库连接 cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver cas.auth ...

  6. POJ 3713 Transferring Sylla【Tarjan求割点】

    题意:给出一个无向图,判断是否任意两点间都存在至少3条互相独立的路,独立指公共顶点只有起点和终点.算法:枚举每个点,删去后用Tarjan判断图中是否存在割点,如果存在则该图不满足三连通性.Tarjan ...

  7. spring的4种事务特性,5种隔离级别,7种传播行为

    spring事务:  事务: 事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败. 事务特性(4种): 原子性 (atomicity):强调事务的不可分割. 一致性 (con ...

  8. Windows 7 编译64位boost库

    1. 官网下载boost 2. 解压boost到D:\Library\boost_1_64_0 3. 打开 VS2015 x64 本机工具命令提示符,输入 "d:" 回车,再输入 ...

  9. 【BZOJ3514】Codechef MARCH14 GERALD07加强版 LCT+主席树

    题解: 还是比较简单的 首先我们的思路是 确定起点 然后之后贪心的选择边(也就是越靠前越希望选) 我们发现我们只需要将起点从后向前枚举 然后用lct维护连通性 因为强制在线,所以用主席树记录状态就可以 ...

  10. JMeter上传案例2

    今天自己的QQ群里有个朋友一直在问JMeter图片上传的问题 原始通过JMeter抓包如下: 参考: http://blog.csdn.net/huashao0602/article/details/ ...