这道题是昨天linkfqy dalao上课讲的一道题

当时他讲的时候就想到了一种玄学的搞法,然后不敢相信自己切掉了

没想到后来CHJ dalao也想到了这种算法,然后发现是对的

后来10min就切掉了

看来以后要活跃一点了

这里主要讲两种算法(想WQS二分这种高深的算法就不讲了)

首先讲题意:一个人它只能在某个时间点去跟看k个他的客人对话,或是结束他和当前这个客人的对话。但是它不能在两个连续的时间段进行讲话,问它最少需要多少时间来和k个客人对话。

1.堆

我们先按时间排序,处理出每一个时间段的长度

然后就建模转化成:n-1个点中取k个并且每两个都不相邻的最少代价和。

这就和一道题很像了,看Luogu P1484&sol

用堆水一水即可

CODE

#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N=500005;
int k,n,x[N],a[N],pre[N],nxt[N],ans;
bool vis[N];
struct data
{
int x,num;
bool operator <(const data &s) const
{
return s.x<x;
}
};
priority_queue<data> small;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i; read(k); read(n);
for (i=1;i<=n;++i)
read(x[i]);
sort(x+1,x+n+1);
for (i=2;i<=n;++i)
{
a[i-1]=x[i]-x[i-1];
pre[i-1]=i-2; nxt[i-1]=i;
small.push((data){a[i-1],i-1});
}
a[0]=a[n]=1e9; pre[n]=n-1; nxt[0]=1;
while (k--)
{
while (vis[small.top().num]) small.pop();
data p=small.top(); small.pop(); ans+=p.x;
p.x=a[p.num]=a[pre[p.num]]+a[nxt[p.num]]-a[p.num];
vis[pre[p.num]]=vis[nxt[p.num]]=1;
pre[p.num]=pre[pre[p.num]]; nxt[pre[p.num]]=p.num;
nxt[p.num]=nxt[nxt[p.num]]; pre[nxt[p.num]]=p.num;
small.push(p);
}
printf("%d",ans);
return 0;
}

2.DP

首先这种题目就是看一眼就想到DP的吧

我们令f[i][j][0/1]表示前i个点中取j个并且第i个点取or不取(1表示取,2表示不取)的最少代价

则很容易写出转移:

  • f[i][j][1]=f[i-1][j-1][0]+a[i]

  • f[i][j][0]=min(f[i-1][j][0],f[i-1][j][1])

首先我们发现i的那一维可以滚动存储优化掉

然后空间就够了,但是时间为O(nk)

然后坚信CF的机子是无敌的满怀信仰地交上去说不定就过了

然后这里我们就要讲一个结论了:

无论怎么取,都只可能取到3*k小的数

Why?很简单,如果所有的数左右都取,算上它自己,也就3个,扩展开就是3*k

所以我们就把时间优化到了O(k^2)

CODE

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=500005,K=5005;
int x[N],a[N],n,k,f[2][K][2],pre,num,tot;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline int min(int a,int b)
{
return a<b?a:b;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j;
read(k); read(n);
for (i=1;i<=n;++i)
read(x[i]); sort(x+1,x+n+1);
for (i=2;i<=n;++i)
x[i-1]=a[i-1]=x[i]-x[i-1];
sort(x+1,x+n); num=3*k<n?x[3*k]:x[n-1];
memset(f[0],63,sizeof(f[0])); f[0][0][0]=f[0][0][1]=0;
int now=0,lst=1,pre=-1;
for (i=1;i<n;++i)
{
if (a[i]>num) continue;
now^=1; lst^=1; memset(f[now],63,sizeof(f[now]));
++tot;
if (i-1!=pre)
{
for (j=1;j<=min(tot,k);++j)
{
f[now][0][0]=f[now][0][1]=0;
f[now][j][1]=min(f[lst][j-1][0],f[lst][j-1][1])+a[i];
f[now][j][0]=min(f[lst][j][0],f[lst][j][1]);
}
} else
{
for (j=1;j<=min(tot,k);++j)
{
f[now][0][0]=f[now][0][1]=0;
f[now][j][1]=f[lst][j-1][0]+a[i];
f[now][j][0]=min(f[lst][j][0],f[lst][j][1]);
}
} pre=i;
}
printf("%d",min(f[tot&1][k][0],f[tot&1][k][1]));
return 0;
}

CF 958E2. Guard Duty (medium)的更多相关文章

  1. Guard Duty (medium) Codeforces - 958E2 || (bzoj 2151||洛谷P1792) 种树 || 编译优化

    https://codeforces.com/contest/958/problem/E2 首先求出N个时刻的N-1个间隔长度,问题就相当于在这些间隔中选K个数,相邻两个不能同时选,要求和最小 方法1 ...

  2. [Codeforces958E2]Guard Duty (medium)(区间DP)

    Description 题目链接 Solution 可以把题目转化一下模型,将间隔取出来,转化为N-1个数,限制不能取相邻两个数,求取K个数的最小价值 设DP[i][j]表示前i个数取j个最大价值(第 ...

  3. CF 85E Guard Towers——二分图染色

    题目:http://codeforces.com/contest/85/problem/E 当然是二分.然后连一个图,染色判断是不是二分图即可.方案数就是2^(连通块个数). 别真的连边!不然时间空间 ...

  4. Guard Duty (hard) Codeforces - 958E3 || uva 1411

    https://codeforces.com/contest/958/problem/E3 当没有三点共线时,任意一个这样的点集都是保证可以找到答案的,(考虑任意一种有相交的连线方案,一定可以将其中两 ...

  5. CF E2 - Daleks' Invasion (medium) (LCA求两点树上路径上的最大边权)

    http://codeforces.com/contest/1184/problem/E2 题意:给出一副图,首先求出这幅图的最小生成树 , 然后修改这幅图上不属于最小生成树的边权,使得修改后的图在求 ...

  6. 决策单调性&wqs二分

    其实是一个还算 trivial 的知识点吧--早在 2019 年我就接触过了,然鹅当时由于没认真学并没有把自己学懂,故今复学之( 1. 决策单调性 引入:在求解 DP 问题的过程中我们常常遇到这样的问 ...

  7. DP 优化方法大杂烩 & 做题记录 I.

    标 * 的是推荐阅读的部分 / 做的题目. 1. 动态 DP(DDP)算法简介 动态动态规划. 以 P4719 为例讲一讲 ddp: 1.1. 树剖解法 如果没有修改操作,那么可以设计出 DP 方案 ...

  8. 20190708三人开黑CF模拟赛

    7月8号晚上8点和两位巨佬开了一场虚拟cf: [Helvetic Coding Contest 2018 online mirror (teams allowed, unrated)] 我这么蔡,只A ...

  9. 越狱Season 1- Episode 16

    Season 1, Episode 16 -Burrows:Don't be. It's not your fault. 不要,不是你的错 -Fernando: Know what I like? 知 ...

随机推荐

  1. Vue CLI3 开启gzip压缩

    gizp压缩是一种http请求优化方式,通过减少文件体积来提高加载速度.html.js.css文件甚至json数据都可以用它压缩,可以减小60%以上的体积. webpack在打包时可以借助 compr ...

  2. 自定义ScrollView 实现上拉下拉的回弹效果--并且子控件中有Viewpager的情况

    onInterceptTouchEvent就是对子控件中Viewpager的处理:左右滑动应该让viewpager消费 public class MyScrollView extends Scroll ...

  3. MySQL——优化嵌套查询和分页查询

    优化嵌套查询 嵌套查询(子查询)可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中.嵌套查询写起来简单,也容易理解.但是,有时候可以被更有效率的连接(JOIN ...

  4. 慕学在线网0.2_users表设计(1)

    1.Django App设计: users-用户管理(任何web中,users表都是第一个被设计的) course-课程管理 organization-机构和教师管理 operation-用户操作管理 ...

  5. MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化

    MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...

  6. Centos7下crontab+shell脚本定期自动删除文件

    问题描述: 最近有个需求,就是rsync每次同步的数据量很多,但是需要保留的数据库bak文件 保留7天就够了,所以需要自动清理文件夹内的bak文件 解决方案: 利用shell脚本来定期删除文件夹内的任 ...

  7. Paramiko和堡垒机实现

    一.Paramiko paramiko模块,基于SSH用于连接远程服务器并执行相关操作. 1.安装:pip install paramiko 2.SSHClient:用于连接远程服务器并执行基本命令 ...

  8. PyQt5--TextDrag

    # -*- coding:utf-8 -*- ''' Created on Sep 21, 2018 @author: SaShuangYiBing Comment: ''' import sys f ...

  9. 【Nginx】什么是Nginx?为什么使用Nginx?

    转文章 一.前言 为毛要用nginx服务器代理,不直接用tomcat 7.0,还做多了一次接请求? 这个是我想问的,公司的新项目是要用Nginx+tomcat7+jdk开发的,用户命名可以直接访问to ...

  10. File类_常见的方法(获取,创建与删除,判断,重命名)

    获取:  1.1获取文本名称  1.2获取文件路劲  1.3获取文件大小  1.4获取文件修改或创建时间 import java.io.File; import java.text.DateForma ...