题目大意

你需要保证第\(i\)天时有第\(a_i\)种书。你可以在任何一天买书,买第\(i\)种书的代价为\(c_i\)。

你最多同时拥有\(k\)本书,如果此时再买书,则必须先扔掉已拥有的一本书。并且如果以后用到那本书则需要重新购买。

问最小的代价使满足\(n\)天中的所有条件都满足。

\(medium : n,k \leq 400000\)且保证所有的\(c_i = 1\)

\(hard : n,k \leq 80\)

\(all : a_i \leq n,c_i \leq 10^6\)

题解

对于\(medium\)来说直接贪心就好。

每次需要删除的时候找出从当前位置往后最后一个出现的删除就好了。

调个\(set\)。注意不能用.(不要问我是怎么知道的)

主要问题在于\(hard\)。

\(n,k\)的范围又小了下来。

这提醒了我们已经不存在贪心的策略了。

不过我们可以从先前的贪心策略中得到启发。

如果我们只盯着一个存放书的位置上看,那么就是一个这个位子上的书不断变化的过程。

变化是为了去满足一些条件,也是因为要去满足下一个条件才变化的。

那么考虑如果将要满足的下一个条件确定了,那么这个位置在满足条件之前不会改变。

可以视作这个位置为了满足某个条件被占用了一段时间。

如果我们提前承受了所有的代价,那么下面我们就要处理收益问题。

这时候的收益即一个数在某一段时间保持不变只为下一次这个数出现的时候少一次购买。

所以我们可以建立这样的模型:

弧线边只连接上一个与其相同的数\(+1\)的位置和该点所在的位置。

还有要注意的一点是 : 不能让所有的流量都去满足其他条件限制

至少应该有一个流量留在主线上。

所以我们可以直接将输入的\(k--\)...

然后跑最小费用最大流即可.

\(medium:\)

#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-')ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);--i)
const int maxn = 400010;
int a[maxn],nx[maxn],ws[maxn];
set<int>s;
bool inq[maxn];int cnt = 0; int main(){
int n,k;read(n);read(k);
memset(ws,0x3f,sizeof ws);
rep(i,1,n) read(a[i]);
per(i,n,1){
nx[i] = ws[a[i]];
ws[a[i]] = i;
}
int ans = 0;
rep(i,1,n){
if(s.count(i)){
s.erase(i);
s.insert(nx[i]);
continue;
}
if(s.size() < k){
++ ans;
s.insert(nx[i]);
}else{
s.erase(--s.end());
s.insert(nx[i]);
++ ans;
}
}
printf("%d\n",ans);
return 0;
}

\(hard:\)

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);--i)
const int maxn = 128;
const int maxnode = maxn;
const int maxedge = maxn*maxn;
const int inf = 0x3f3f3f3f;
struct Edge{
int to,next,cap,cost;
}G[maxedge<<1];
int head[maxnode],cnt = 1;
void add(int u,int v,int c,int d){
G[++cnt].to = v;
G[cnt].next = head[u];
head[u] = cnt;
G[cnt].cap = c;
G[cnt].cost = d;
}
inline void insert(int u,int v,int c,int d){
add(u,v,c,d);add(v,u,0,-d);
}
#define v G[i].to
int dis[maxn],flow[maxn],p[maxn];
bool inq[maxn];int S,T;
int ans;
inline bool spfa(){
queue<int>q;
memset(dis,0x3f,sizeof dis);
dis[S] = 0;flow[S] = inf;
inq[S] = true;
q.push(S);
while(!q.empty()){
int u = q.front();q.pop();
for(rg i = head[u];i;i=G[i].next){
if(dis[v] > dis[u] + G[i].cost && G[i].cap){
dis[v] = dis[u] + G[i].cost;
flow[v] = min(flow[u],G[i].cap);
p[v] = i;
if(!inq[v]){
q.push(v);
inq[v] = true;
}
}
}inq[u] = false;
}if(dis[T] == dis[0]) return false;
ans += dis[T]*flow[T];
for(rg u=T;u != S;u = G[p[u]^1].to)
G[p[u]].cap -= flow[T],G[p[u]^1].cap += flow[T];
return true;
}
#undef v
int a[maxn],c[maxn],ws[maxn];
int main(){
int n,k;read(n);read(k);
-- k;
rep(i,1,n) read(a[i]);
rep(i,1,n) read(c[i]);
S = n + 1;T = n+2;
insert(S,1,k,0);
insert(n,T,k,0);
rep(i,1,n-1) insert(i,i+1,k,0);
rep(i,1,n){
ans += c[a[i]];
if(ws[a[i]] != 0){
if(ws[a[i]]+1 == i) ans -= c[a[i]];
else insert(ws[a[i]]+1,i,1,-c[a[i]]);
}
ws[a[i]] = i;
}
while(spfa());
printf("%d\n",ans);
return 0;
}

Codeforces 802 ABC. Heidi and Library的更多相关文章

  1. 题解-CF802C Heidi and Library (hard)

    题面 CF802C Heidi and Library (hard) 有一个大小为 \(k\) 的空书架.有 \(n\) 天和 \(n\) 种书,每天要求书架中有书 \(a_i\).每天可以多次买书, ...

  2. 【CF802C】Heidi and Library(网络流)

    [CF802C]Heidi and Library(网络流) 题面 CF 洛谷 题解 前面两个Easy和Medium都是什么鬼玩意啊.... 不难发现如果这天的要求就是第\(a_i\)种书的话,那么\ ...

  3. 【CF802C】Heidi and Library (hard) 费用流

    [CF802C]Heidi and Library (hard) 题意:有n个人依次来借书,第i人来的时候要求书店里必须有种类为ai的书,种类为i的书要花费ci块钱购入.而书店的容量只有k,多余的书只 ...

  4. C. Heidi and Library (神奇的网络流)

    C. Heidi and Library 题意 有 n 种分别具有价格 b 的书 a ,图书馆里最多同时存放 k 本书,已知接下来 n 天每天都有一个人来看某一本书,如果图书馆里没有则需要购买,问最少 ...

  5. Codeforces 802 补题

    codeforces802 A-O Helvetic Coding Contest 2017 online mirror A  Heidi and Library (easy) 水题 同B #incl ...

  6. 贪心算法 Heidi and Library (easy)

    A. Heidi and Library (easy) time limit per test 2 seconds memory limit per test 256 megabytes input ...

  7. CF802C Heidi and Library hard 费用流 区间k覆盖问题

    LINK:Heidi and Library 先说一下简单版本的 就是权值都为1. 一直无脑加书 然后发现会引起冲突,可以发现此时需要扔掉一本书. 扔掉的话 可以考虑扔掉哪一本是最优的 可以发现扔掉n ...

  8. 【贪心】codeforces B. Heidi and Library (medium)

    http://codeforces.com/contest/802/problem/B [题意] 有一个图书馆,刚开始没有书,最多可容纳k本书:有n天,每天会有人借一本书,当天归还:如果图书馆有这个本 ...

  9. 【网络流】codeforces C. Heidi and Library (hard)

    http://codeforces.com/contest/802/problem/C

随机推荐

  1. smarty模板及其应用

    Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一.它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离. ...

  2. HackerRank - fibonacci-modified 【大数】

    思路 用PYTHON 或 JAVA 干掉 AC代码 a, b, n = map(int, input().split()) for i in range (2, n, 1) : temp = b b ...

  3. JFreeChart应用实例-折线图

    http://www.tuicool.com/articles/Nr2Yna JFreeChart在制作折线图的时候可以使用两种不同的方式 package Line; import java.awt. ...

  4. 对matrix,dataframe的操作函数

    1.每行(列)的平均值:rowMeans() ; colMeans() 输入:数值型矩阵:数值型数据框 输出:向量 2.每行(列)的总和:rowSums() ;colSums() 输入:数值型矩阵,数 ...

  5. 语义web基础知识学习

    最近找了一本书,<语义web技术基础>----Pascal Hitzler等编著的.因为最近在看关于自然语言处理的一些东西,就顺带翻了一下,做一点学习笔记,方便以后查看. 本书的作者 Pa ...

  6. tomcat 日志禁用

    1.禁用catalina.out日志通过修改catalina.sh配置可以控制tomcat不生成该文件只要将if [ -z "$CATALINA_OUT" ] ; then CAT ...

  7. Kafka高可用环境搭建

    Apache Kafka是分布式发布-订阅消息系统,在 kafka官网上对 kafka 的定义:一个分布式发布-订阅消息传递系统. 它最初由LinkedIn公司开发,Linkedin于2010年贡献给 ...

  8. <转>xshell的快捷键

    xshell中现有的快捷键 快捷方式键 说明 Alt + N 与文件菜单的新建相同 Alt + O 与文件菜单的打开相同 Alt + C 与文件菜单的断开相同 Alt + Enter 切换到全屏模式 ...

  9. 集成Spring web.xml配置总结

    1.web.xml 的加载顺序是:ServletContext -> context-param -> listener -> filter -> servlet 1.serv ...

  10. HBase-存储-文件

    文件 HBase使用一个HDFS中可配置的根目录,默认设为“/hbase”.可使用hadoop fs -lsr /hbase查看目录结构,文件可以被分为两类,一类位于HBase根目录下,另一类位于根目 ...