题目大意:

  传送门

  给一个长度为$n(n<=200)$的数列$h$,再给$m$个可以无限使用的操作,第$i$个操作为给长度为花费$c_i$的价值给长度为$l_i$的数列子序列+1或-1,求将数列变为不下降数列的最小花费。

题解:

第一部分(上下界最小费用可行流):  

  设$h_0=-inf,h_{n+1}=inf$,令$a$为$h$的差分数组,即$a_i=h_{i}-h_{i-1}$。考虑当对于区间$[l,r]$操作时(比如+1),相当于$a_{r+1}$减少1,$a_{l}$增加1。若将$a$数组看做点集,这个变化相当于从$r+1$到$l$的一条流量为$1$的有向边,反之(-1)亦然。

  显然问题相当于把$a$数组元素均变为 不为0。那么我们由S向$a_{i}>0$的位置连$flow=[0,a_{i}],cost=0$的边,表示${i}$可以减少流量上下界,对于$a_{i}<0$的位置,我们至少要使其增加$-a_i$所以我们向$T$连$flow=[-a_i,inf],cost=0$的边。对于每个操作我们由于可无限使用我们就给所有合法位置连$flow=[0,inf],cost=c_{i}$的边,然后我们可以跑一个上下界解决问题。

  等等,这样的确解决了问题,不过我们观察一下这个图,会发现上下界源点只连向了$T$,而上下界汇点只被那些$a_{i}<0$的点连接到。

  我们把这个图转化一下,会发现对于上面的建图方式,我们只把$a_{i}<0$的边建成$flow=-a_i,cost=0$的边即可,根本不需要跑上下界。这就是另外一种思考方式。

第二部分(最小费用最大流):

  我们考虑那些$a_{i}<0$的点变为$0$一定比使其变为任一整数更优秀,同时这也是我们的判断有没有解的依据。

  所以我们就直接由$a_{i}<0$的点连向$T$的边为$flow=-a_i,cost=0$即可,如果所有连向$T$的边都流满,说明有解,同时由于上述性质,一定是最优解。

  

  不过这两个时间复杂度并没有太大区别。

代码:

 #include "bits/stdc++.h"

 using namespace std;

 #define inf 0x3f3f3f3f

 inline int read() {
int s=,k=;char ch=getchar ();
while (ch<''|ch>'') ch=='-'?k=-:,ch=getchar();
while (ch>&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
} const int N=1e3+; struct edges {
int v,cap,cost;edges *pair,*last;
}edge[N*N],*head[N];int cnt; inline void push(int u,int v,int cap,int cost) {
edge[++cnt]=(edges){v,cap,cost,edge+cnt+,head[u]},head[u]=edge+cnt;
edge[++cnt]=(edges){u,,-cost,edge+cnt-,head[v]},head[v]=edge+cnt;
} int S,T,ss,tt,n,fl,m;
int piS,vis[N];
long long cost; inline int aug(int x,int w) {
if (x==T) return cost+=1ll*piS*w,fl+=w,w;
vis[x]=true;
int ret=;
for (edges *i=head[x];i;i=i->last)
if (i->cap&&!i->cost&&!vis[i->v]) {
int flow=aug(i->v,min(i->cap,w));
i->cap-=flow,i->pair->cap+=flow,ret+=flow,w-=flow;
if (!w) break;
}
return ret;
} inline bool modlabel() {
static int d[N];
memset(d,0x3f,sizeof d);d[T]=;
static deque<int> q;q.push_back(T);
int dt;
while (!q.empty()) {
int x=q.front();q.pop_front();
for (edges *i=head[x];i;i=i->last)
if (i->pair->cap&&(dt=d[x]-i->cost)<d[i->v])
(d[i->v]=dt)<=d[q.size()?q.front():]
?q.push_front(i->v):q.push_back(i->v);
}
for (int i=S;i<=T;++i)
for (edges *j=head[i];j;j=j->last)
j->cost+=d[j->v]-d[i];
piS+=d[S];
return d[S]<inf;
} inline void solve() {
piS = cost = ;
while(modlabel())
do memset(vis,,sizeof vis);
while(aug(S, inf));
} int h[N],a[N],c[N],l[N],typ[N];
int f[N],g[N]; int main(){
n=read(),m=read();
for (int i=;i<=n;++i)
h[i]=read();
for (int i=n;i>;--i)
h[i]=h[i]-h[i-];
h[]=inf,h[n+]=inf;
ss=n+,tt=ss+,T=tt+;
char opt[];
for (int i=;i<=m;++i) {
scanf("%s",opt),l[i]=read(),c[i]=read();
typ[i]=opt[]=='+';
}
++n;
for (int i=;i<=n;++i)
if (h[i] > )
push(ss,i,h[i],);
else if(h[i]<) push(i,tt,inf,),a[i]=-h[i],a[tt]+=h[i],push(i,T,a[i],);
push(tt,ss,inf,);
push(S,tt,-a[tt],);
memset(f,0x3f,sizeof(f));
f[]=;
memcpy(g,f,sizeof g);
for (int j=;j<=m;++j)
for (int k=l[j];k<=n;k+=l[j])
if(typ[j])
for (int i=n-;i>=l[j];--i)
f[i]=min(f[i],f[i-l[j]]+c[j]);
else
for (int i=n-;i>=l[j];--i)
g[i]=min(g[i],g[i-l[j]]+c[j]);
// puts()
for (int j=;j<=m;++j)
if (typ[j]){
if (f[l[j]]==c[j])
for (int i=l[j]+;i<=n;++i)
push(i,i-l[j],inf,c[j]);
}else
if (g[l[j]]==c[j])
for (int i=;i+l[j]<=n;++i)
push(i,i+l[j],inf,c[j]);
solve();
if (fl==-a[tt])
printf("%lld\n",cost);
else puts("-1");
}

上下界

 #include "bits/stdc++.h"

 using namespace std;

 #define inf 0x3f3f3f3f

 inline int read() {
int s=,k=;char ch=getchar ();
while (ch<''|ch>'') ch=='-'?k=-:,ch=getchar();
while (ch>&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
} const int N=1e3+; struct edges {
int v,cap,cost;edges *pair,*last;
}edge[N*N],*head[N];int cnt; inline void push(int u,int v,int cap,int cost) {
edge[++cnt]=(edges){v,cap,cost,edge+cnt+,head[u]},head[u]=edge+cnt;
edge[++cnt]=(edges){u,,-cost,edge+cnt-,head[v]},head[v]=edge+cnt;
} int S,T,ss,tt,n,fl,m;
int piS,vis[N];
long long cost; inline int aug(int x,int w) {
if (x==T) return cost+=1ll*piS*w,fl+=w,w;
vis[x]=true;
int ret=;
for (edges *i=head[x];i;i=i->last)
if (i->cap&&!i->cost&&!vis[i->v]) {
int flow=aug(i->v,min(i->cap,w));
i->cap-=flow,i->pair->cap+=flow,ret+=flow,w-=flow;
if (!w) break;
}
return ret;
} inline bool modlabel() {
static int d[N];
memset(d,0x3f,sizeof d);d[T]=;
static deque<int> q;q.push_back(T);
int dt;
while (!q.empty()) {
int x=q.front();q.pop_front();
for (edges *i=head[x];i;i=i->last)
if (i->pair->cap&&(dt=d[x]-i->cost)<d[i->v])
(d[i->v]=dt)<=d[q.size()?q.front():]
?q.push_front(i->v):q.push_back(i->v);
}
for (int i=S;i<=T;++i)
for (edges *j=head[i];j;j=j->last)
j->cost+=d[j->v]-d[i];
piS+=d[S];
return d[S]<inf;
} inline void solve() {
piS = cost = ;
while(modlabel())
do memset(vis,,sizeof vis);
while(aug(S, inf));
} int h[N],a[N],c[N],l[N],typ[N];
int f[N],g[N]; int main(){
n=read(),m=read();
for (int i=;i<=n;++i)
h[i]=read();
for (int i=n;i>;--i)
h[i]=h[i]-h[i-];
h[]=inf,h[n+]=inf;
// ss=n+2,tt=ss+1,T=tt+1;
char opt[];
for (int i=;i<=m;++i) {
scanf("%s",opt),l[i]=read(),c[i]=read();
typ[i]=opt[]=='+';
}
++n;T=n+;
for (int i=;i<=n;++i)
if (h[i] > )
push(S,i,h[i],);
else if(h[i]<) push(i,T,-h[i],),a[tt]+=h[i];//,push(i,T,a[i],0);
// push(tt,ss,inf,0);
// push(S,tt,-a[tt],0);
memset(f,0x3f,sizeof(f));
f[]=;
memcpy(g,f,sizeof g);
for (int j=;j<=m;++j)
for (int k=l[j];k<=n;k+=l[j])
if(typ[j])
for (int i=n-;i>=l[j];--i)
f[i]=min(f[i],f[i-l[j]]+c[j]);
else
for (int i=n-;i>=l[j];--i)
g[i]=min(g[i],g[i-l[j]]+c[j]);
for (int j=;j<=m;++j)
if (typ[j]){
if (f[l[j]]==c[j])
for (int i=l[j]+;i<=n;++i)
push(i,i-l[j],inf,c[j]);
}else
if (g[l[j]]==c[j])
for (int i=;i+l[j]<=n;++i)
push(i,i+l[j],inf,c[j]);
solve();
// printf("%d %d\n",fl);
if (fl==-a[tt])
printf("%lld\n",cost);
else puts("-1");
}

最大流

【BZOJ 5222】[Lydsy2017省队十连测]怪题的更多相关文章

  1. bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树

    [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 93  Solved: 53[Submit][Status][ ...

  2. bzoj 5216: [Lydsy2017省队十连测]公路建设

    5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 66  Solved: 37[Submit][St ...

  3. bzoj 5218: [Lydsy2017省队十连测]友好城市

    题意: 这题显然直接tarjan是做不了的. 这里安利另一个求SCC的算法Kosaraju,学习的话可以见这篇博客 于是结合莫队,我们有了个暴力. 发现主要瓶颈是dfs过程中找最小的未经过的点,我们用 ...

  4. bzoj 5217: [Lydsy2017省队十连测]航海舰队

    Description Byteasar 组建了一支舰队!他们现在正在海洋上航行着.海洋可以抽象成一张n×m 的网格图,其中有些位置是" .",表示这一格是海水,可以通过:有些位置 ...

  5. BZOJ 5215: [Lydsy2017省队十连测]商店购物

    裸题 注意+特判 #include<cstdio> using namespace std; const int mod=1e9+7; int F[1000005],mi[10000005 ...

  6. @bzoj - 5219@ [Lydsy2017省队十连测]最长路径

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 在Byteland一共有n个城市,编号依次为1到n,形成一个n个 ...

  7. BZOJ5243 : [Lydsy2017省队十连测]绝版题

    要找的就是这棵树的带权重心,以带权重心为根时每棵子树的权值和不超过总权值和的一半. 因此按$\frac{v[i]}{\sum v[i]}$的概率随机选取一个点$x$,则重心有$\frac{1}{2}$ ...

  8. Lydsy2017省队十连测

    5215: [Lydsy2017省队十连测]商店购物 可能FFT学傻了,第一反应是前面300*300背包,后面FFT... 实际上前面背包,后面组合数即可.只是这是一道卡常题,需要注意常数.. //A ...

  9. 2018.09.26 bzoj5218: [Lydsy2017省队十连测]友好城市(回滚莫队)

    传送门 比较简单的一道回滚莫队吧. 每次询问用bitset优化kosaraju统计答案. 就是有点难调. 然后向dzyo学长学习了回滚莫队的一种简洁的实现方式,就是直接建立一个sqrt(m)∗sqrt ...

随机推荐

  1. 使用Interlocked在多线程下进行原子操作,无锁无阻塞的实现线程运行状态判断

    巧妙地使用Interlocked的各个方法,再无锁无阻塞的情况下判断出所有线程的运行完成状态. 昨晚耐着性子看完了clr via c#的第29章<<基元线程同步构造>>,尽管这 ...

  2. Eclipse常见设置

    当新建一个workspace时,习惯做下面的设置: 1. 在eclipse中,默认的Text file encoding是GBK(操作系统是中文简体):如果操作系统是中文繁体,默认是MS950(Big ...

  3. 赋给个人账户sudo的全部root执行权限

    sudo visudo 输入root账户密码后,会自动打开sudoers文件编辑 在root     ALL=(ALL)    ALL此行下增加一行 user ALL=(ALL)    NOPASSW ...

  4. Map 遍历分析

    1. 阐述 对于Java中Map的遍历方式,很多文章都推荐使用entrySet,认为其比keySet的效率高很多.理由是:entrySet方法一次拿到所有key和value的集合:而keySet拿到的 ...

  5. 返回空的list集合*彻底删除删除集合*只是清空集合

    ---------- 要求返回空的List集合----------- List<String> allList = Collections.emptyList();// 返回空的List集 ...

  6. jquery 设置占位符

    <script type="text/javascript">    $(document).ready(function(){       $('.inputfiel ...

  7. JTA 分布式事务

    什么是JTA - 2009-07-25 18:31:06|  分类: 技术文章|举报|字号 订阅     什么是JTA? Java Transaction API(Java事务API) (JTA)Ja ...

  8. Web安全学习计划

    http://cisps.org/bbs/viewtopic.php?f=71&t=26125 标题为Web安全学习计划,实属我的愿望:将下面这份Web学习清单完善成为一个Web安全,学习计划 ...

  9. React+ANTD项目使用后的一些关于生命周期比较实用的心得

    1. constructor() constructor(props){ super(props) this.state=({ }) } 一定先写super  可以接收从父组件传来的值 父组件往子组件 ...

  10. Download and Install Apache Zookeeper on Ubuntu

    http://www.techburps.com/misc/download-and-install-apache-zookeepr/36 In previous article of this Bi ...