题解-bzoj1283序列 & bzoj4842 [Neerc2016]Delight for a Cat
因为这两题有递进关系,所以放一起写
Problem
题意概要:一个长度为 \(n\) 的序列\(\{c_i\}\),求一个子集,使得原序列中任意长度为 \(m\) 的子串中被选出的元素不超过\(K\)个,并且选出的元素之和最大。
bzoj 4842 Please contact lydsy2012@163.com! (可以下数据自测 然而还需要spj,upd:loj6079好像是一样的)
题意概要:构造一个长度为\(n\)的\(12\)序列\(\{a_i\}\),\(a_i=1\)或\(2\)的贡献分别为\(s_i,t_i\),对于任意长度为\(k\)的子串,至少要有\(t_1\)个\(1\),至少要有\(t_2\)个\(2\),问这\(n\)个小时的最大收益
Solution-bzoj1283
这题和网络流24题-最长\(k\)可重区间集问题很像,只不过这里运用了点线互换的套路。
限制对于每个区间选出的元素不能超过\(k\)个,等价于把元素视作一条长度为\(k\)的线段,每个点不能被覆盖超过\(k\)次
每个点被覆盖不超过\(k\)次就可以用网络流解决了,利用流量限制\(k\)
- 建立一个主轴(连边\(i\rightarrow i+1\),流量\(\inf\),费用\(0\))用以传递流量
- 对每个点建出线段(连边\(i\rightarrow i+k\),流量\(1\),费用\(c_i\))
这样如果想取得一个权值\(c_i\),必须有\(1\)的流量从\(i\)开始走费用为\(c_i\)的那条边,而只要设置源点流量为\(k\),则对于每个截面的流量不会超过\(k\),化为实际意义即每个点被覆盖不超过\(k\)次,跑最大费用最大流即可
Solution-bzoj4842
简化题目
现将这题的 “二者选其一” 转化为上一题的 “选与不选”:先假定序列全部选\(2\),再考虑对于每个位置换不换成\(1\)(\(ans=\sum e_i\),令\(n\)个点权值为\(a_i=s_i-e_i\),考虑每个点选与不选)
上一题是每个点被覆盖不超过\(k\)次
考虑这题变成了交换,设交换\(x\)次,则选择\(x\)个\(1\),选择\(k-x\)个\(2\),由于\(t_1\leq x\\t_2\leq k-x\),即\(t_1\leq x\leq k-t_2\)
即每个点被覆盖不超过\(k-t2\)次,不少于\(t_1\)次,不多于\(k-t_2\)次,上下界网络流……
然而凑巧的是,前天我刚想到一个奇妙的下界网络流方法 实际很简单,比如要一个一条边的流量大于等于某个数\(t\),则只要往这条边的入度注满\(s\)的流,然后在入度处拉出一条流量上界为\(s-t\)的边,则原边流量刚好大于等于\(t\)(即利用限制分流保证原边流量下界)
所以这题就可以做了,类似于上一题,这里不能被覆盖超过\(k-t_2\)次,即源点流量为\(k-t_2\),不少于\(t_1\)次,利用上面这个方法就是将主轴的流量上界设定为\(k-t_2-t_1\),这样对于每个点都会至少有\((k-t_2)-(k-t_2-t_1)=t_1\)次覆盖了
但是考虑若像上一题那样源点只连第一个位置,会使得前面\(k\)个点之间的主轴承受不住,所以需要源点需要往前\(k\)个点都连一条无限流量无费用的边
细化做法:
- 虚源点往源点连边(流量\(k-t_2\),费用\(0\))
- 源点往\(i,i\in[1,k]\)连边(流量\(\inf\),费用\(0\))
- \(i\)往\(i+1\)连边(流量\(k-t_1-t_2\),费用\(0\))
- \(i\)往\(i+k\)连边,若\(i+k>n\)则连向\(t(t=n+1)\)(流量\(1\),费用\(s_i-e_i\))
跑最大费用最大流即可
哦,对了,听说这两题还可以线性规划玩
Code
bzoj1283
#include <bits/stdc++.h>
using namespace std;
inline int read(int&x){
char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();return x;
}
const int N=4050,inf = 0x3f3f3f3f;
struct Edge{int v,w,c,nxt;}a[N];
int head[N],n,m,s,t,k,_;
inline void add(int u,int v,int w,int c){
a[_].v=v,a[_].w=w,a[_].c=c,a[_].nxt=head[u],head[u]=_++;
a[_].v=u,a[_].w=0,a[_].c=-c,a[_].nxt=head[v],head[v]=_++;
}
namespace max_cost{
int q[N*10],he,ta;
int dis[N],inq[N],vis[N],dfc=0;
bool bfs(){
for(int i=0;i<t;++i)dis[i]=-inf,inq[i]=0;
dis[q[he=ta=1]=t]=0,inq[t]=1;
int x;while(he<=ta){
inq[x=q[he++]]=0;
for(int i=head[x];~i;i=a[i].nxt)
if(a[i^1].w>0&&dis[a[i].v]<dis[x]-a[i].c){
dis[a[i].v]=dis[x]-a[i].c;
if(!inq[a[i].v])q[++ta]=a[i].v,inq[a[i].v]=1;
}
}return dis[s]!=-inf;
}
int dfs(int x,int flw){
if(x==t||!flw)return flw;
int res=0,tmp;vis[x]=dfc;
for(int i=head[x];~i;i=a[i].nxt)
if(vis[a[i].v]!=dfc && a[i].w>0 && dis[a[i].v]==dis[x]-a[i].c)
if(tmp=dfs(a[i].v,min(flw-res,a[i].w))){
a[i].w-=tmp,a[i^1].w+=tmp,res+=tmp;
if(res==flw)return res;
}
return res;
}
void main(){
int flw,ans=0;
while(bfs())
for(vis[t]=dfc;vis[t]==dfc;){
++dfc;flw=dfs(s,inf);
ans+=flw*dis[s];
}
printf("%d\n",ans);
}
}
int main(){
read(n),read(m),read(k);s=0,t=n+1;
for(int i=0;i<=t;++i)head[i]=-1;
add(s,1,k,0);
for(int i=1,x;i<=n;++i){
add(i,i+1,inf,0);
add(i,min(i+m,t),1,read(x));
}
max_cost::main();
return 0;
}
bzoj4842
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename _Tp> inline _Tp read(_Tp&x){
char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')ob=1,c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=1010,M=8010,flow_inf = 0x3f3f3f3f;
struct Edge{int v,w,c,nxt;}a[M];
int head[N],sv[N],ev[N],id[M],state[N];
int n,k,t1,t2;
int s,t,ss,_;
ll ans;
inline void add(int u,int v,int w,int c){
a[_].v=v,a[_].w=w,a[_].c=+c,a[_].nxt=head[u],head[u]=_++;
a[_].v=u,a[_].w=0,a[_].c=-c,a[_].nxt=head[v],head[v]=_++;
}
namespace max_cost{
const ll dis_inf = 0x3f3f3f3f3f3f3f3f;
int q[N*170],inq[N],vis[N];
int he,ta,dfc=0;
ll dis[N];
bool bfs(){
for(int i=t;i;--i)inq[i]=0,dis[i]=-dis_inf;
dis[q[he=ta=1]=t]=0,inq[t]=true;
int x;
while(he<=ta){
inq[x=q[he++]]=false;
for(int i=head[x];~i;i=a[i].nxt)
if(a[i^1].w>0 && dis[a[i].v]<dis[x]-a[i].c){
dis[a[i].v]=dis[x]-a[i].c;
if(!inq[a[i].v])inq[q[++ta]=a[i].v]=true;
}
}return dis[s]!=-dis_inf;
}
int dfs(int x,int flw){
if(x==t||!flw)return flw;
int res(0),tmp;vis[x]=dfc;
for(int i=head[x];~i;i=a[i].nxt)
if(vis[a[i].v]!=dfc && a[i].w>0 && dis[a[i].v]==dis[x]-a[i].c)
if(tmp=dfs(a[i].v,min(flw-res,a[i].w))){
a[i].w-=tmp,a[i^1].w+=tmp,res+=tmp;
if(res==flw)return res;
}
return res;
}
void main(){
int flw;
while(bfs())
for(vis[t]=dfc;vis[t]==dfc;){
++dfc;flw=dfs(s,flow_inf);
ans+=flw*dis[s];
}
printf("%lld\n",ans);
}
}
int main(){
scanf("%d%d%d%d",&n,&k,&t1,&t2);
s=n+1,ss=n+2,t=n+3;
for(int i=t;i;--i)head[i]=-1;
add(s,ss,k-t2,0);
for(int i=1;i<=n;++i)scanf("%d",sv+i);
for(int i=1;i<=n;++i)scanf("%d",ev+i),ans+=ev[i];
for(int i=1;i<=k;++i)add(ss,i,flow_inf,0);
for(int i=1;i<=n;++i){
add(i,i+1>n?t:i+1,k-t1-t2,0);
add(i,i+k>n?t:i+k,1,sv[i]-ev[i]);
id[_-1]=i;
}
max_cost::main();
for(int i=0;i<_;++i)
if(id[i])
state[id[i]]=(a[i].w>0);
for(int i=1;i<=n;++i)putchar(state[i]?'S':'E');
putchar('\n');return 0;
}
题解-bzoj1283序列 & bzoj4842 [Neerc2016]Delight for a Cat的更多相关文章
- bzoj4842: [Neerc2016]Delight for a Cat
bzoj4842 这是一道网络流的题(大家都看出来了吧) 首先我们简化一下题目,选出最关键的部分(就是知道什么和要求什么,还有条件) 我们在这里把睡觉设为0,至少有t0时间在睡觉,把打隔膜设为1,至少 ...
- 【BZOJ4842】[Neerc2016]Delight for a Cat 线性规划+费用流
[BZOJ4842][Neerc2016]Delight for a Cat Description ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打 ...
- [bzoj4842][bzoj1283][Neerc2016]Delight for a Cat/序列_线性规划_费用流
4842: [Neerc2016]Delight for a Cat_1283: 序列 题目大意:ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜 ...
- 【bzoj4842】[Neerc2016]Delight for a Cat 线性规划与网络流
题目描述 $n$ 个连续的位置,每个位置可以填入 S 和 E ,第 $i$ 个位置填入 S 可以获得 $s_i$ 的收益,填入 E 可以获得 $e_i$ 的收益.要求每连续的 $k$ 个位置必须包含至 ...
- bzoj 4842 [Neerc2016]Delight for a Cat 最小费用最大流,线性规划
题意:有n个小时,对于第i个小时,睡觉的愉悦值为si,打隔膜的愉悦值为ei,同时对于任意一段连续的k小时,必须至少有t1时间在睡觉,t2时间在打隔膜.如果要获得的愉悦值尽 量大,求最大的愉悦值和睡觉还 ...
- BZOJ.4842.[NEERC2016]Delight for a Cat(费用流)
BZOJ 参考这儿. 首先如果一个活动的时间满足条件,那么另一个活动也一定满足.还有就是这题就是费用流没有为什么.不妨假设最初所有时间都用来睡觉,那么我们要对每个\(k\)大小区间选出\([t2,k- ...
- bzoj 4842: [Neerc2016]Delight for a Cat
Description ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜 ,因此一个小时内他只能选择睡觉或者打隔膜,当然他也必须选择睡觉或打隔膜, ...
- bzoj 4842: [Neerc2016]Delight for a Cat【最小费用最大流】
考试题搞了好久也没懂-- 正解应该是线性规划 https://www.cnblogs.com/CQzhangyu/p/7894559.html 可是不会写啊 如果从网络流的角度来体会大概是这样 htt ...
- 题解-[HNOI2016]序列
题解-[HNOI2016]序列 [HNOI2016]序列 给定 \(n\) 和 \(m\) 以及序列 \(a\{n\}\).有 \(m\) 次询问,每次给定区间 \([l,r]\in[1,n]\),求 ...
随机推荐
- 9.组合模式(Composite Pattern)
动机(Motivate): 组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素 ...
- STM32学习笔记:【002】BIN文件通过ST-LINK烧录STM32芯片
以下提供2种下载方式 KEIL编译下载 KEIL 5 在开发中还算是比较强大的一种平台.在开发中通过编译再下载会显得很方便. 尽管这个是老生常谈的问题,但还是在这里补全这个设置步骤 1.点击“魔法棒” ...
- SQL Server2012安装流程
今天手比较抽风,把原来的SQL Server给卸载了,卸载还卸了半天,真是…… 安装时找了好多教程,结果都不是很详细,然后准备自己摸索一下,把这个过程记录下来,供大家参考,如果有不当的地方,欢迎指正, ...
- npm离线安装插件
公司内部网络与外部网络隔离,导致npm无法通过npm install安装,只能通过离线安装. 要求: 两台机器(内网一台,外网一台) 两台机器上都已安装好的node和npm 以内网机器安装ftpsyn ...
- 使用jQuery插件时避免重复引入jquery.js文件
当一个页面使用多个jQuery插件时,需要避免重复引入jquery.js文件,因为后面映入的jQuery.js文件中定义的jQuery对象会覆盖掉前面的jQuery对象,导致之前定义的jQuery插件 ...
- ASP.NET Web API 2 使用 DelegatingHandler(委托处理程序)实现签名认证
Ø 前言 在前一篇ASP.NET Web API 2 使用 AuthorizationFilter(授权过滤器)实现 Basic 认证文章中实现了采用 Basic 认证的方式,但是这种方式存在安全隐 ...
- 利用DNSLOG获取看不到的信息(给盲注带上眼镜)
一.前言 本文原创作者:sucppVK,本文属i春秋原创奖励计划,未经许可禁止转载! 毕业设计总算搞得差不多了,这个心累啊.这不,完成了学校的任务,赶紧回来给蛋总交作业.今天给大家分享一个姿势吧,不是 ...
- 【python小练】0010
第 0010 题:使用 Python 生成类似于下图中的字母验证码图片 思路: 1. 随机生成字符串 2. 创建画布往上头写字符串 3. 干扰画面 code: # codeing: utf-8 fro ...
- python 爬虫得到网页的图片
import urllib.request,os import re # 获取html 中的内容 def getHtml(url): page=urllib.request.urlopen(url) ...
- QIM量化
基于量化思想的水印嵌入模型的主要目的是为了实现盲检测.其主要思想是根据水印信息的不同将原始载体数据量化到不同的量化区间,而检测时根据所属的量化区间来识别水印信息.常见的两种量化方式是QIM和SCS方法 ...