BZOJ 1283 序列

1283: 序列

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 542  Solved: 311
[Submit][Status][Discuss]

Description

给出一个长度为 的正整数序列Ci,求一个子序列,使得原序列中任意长度为 的子串中被选出的元素不超过K(K,M<=100) 个,并且选出的元素之和最大。

Input

第1行三个数N,m,k。 接下来N行,每行一个字符串表示Ci。

Output

最大和。

Sample Input

10 5 3
4 4 4 6 6 6 6 6 4 4

Sample Output

30

HINT

20%的数据:n<=10。
100%的数据:N<=1000,k,m<=100。Ci<=20000。

Source

首先我们我们贪心可以得出每m个元素里必定选k个
我们考虑对i+m选不选对于i选不选是否合法是不影响的
这样我们就可以建图
s=1  t=n+2
<s,1,k,0>    <n+1,t,k,0>
<i,min(i+m,n+1),1,a[i]>  <i,i+1,k,0>
跑最大费用流就可以了
#include <bits/stdc++.h>
#define ll long long
#define inf 1e9+10
#define eps 1e-7
using namespace std;
inline int read(){
	int x=0;int f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
const int MAXN=1e6+10;
struct node{
	int y,next,flow,w,back;
}e[MAXN];
int len,linkk[MAXN],dis[MAXN],vis[MAXN],ans,s,t,n,m,k,a[MAXN];
inline void insert(int x,int y,int f,int w){
	e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;e[len].back=len+1;e[len].flow=f;e[len].w=w;
	e[++len].y=x;e[len].next=linkk[y];linkk[y]=len;e[len].back=len-1;e[len].flow=0;e[len].w=-w;
}
inline bool spfa(){
	deque<int>q;
	for(int i=s;i<=t;i++) dis[i]=-inf,vis[i]=0;
	q.push_back(t);dis[t]=0;vis[t]=1;
	while(!q.empty()){
		int tn=q.front();q.pop_front();
		for(int i=linkk[tn];i;i=e[i].next){
			if(e[e[i].back].flow&&dis[e[i].y]<dis[tn]-e[i].w){
				dis[e[i].y]=dis[tn]-e[i].w;
				if(!vis[e[i].y]){
					if(!q.empty()&&dis[e[i].y]>dis[q.front()]) q.push_front(e[i].y);
					else q.push_back(e[i].y);
					vis[e[i].y]=1;
				}
			}
		}
		vis[tn]=0;
	}
	return dis[s]!=-inf;
}
inline int getcost(int x,int flow){
	vis[x]=1;int f=0,d;
	if(x==t) return flow;
	for(int i=linkk[x];i;i=e[i].next){
		if(e[i].flow&&dis[e[i].y]==dis[x]-e[i].w&&!vis[e[i].y]){
			if(d=getcost(e[i].y,min(e[i].flow,flow-f))){
				f+=d;e[i].flow-=d;e[e[i].back].flow+=d;
				ans+=e[i].w*d;if(f==flow) return flow;
			}
		}
	}
	return f;
}
inline void zkw(){
	while(spfa()){
		vis[t]=1;
		while(vis[t]){
			for(int i=s;i<=t;i++) vis[i]=0;
			getcost(s,inf);
		}
	}
}
int main(){
	n=read();m=read();k=read();s=0;t=n+2;
	for(int i=1;i<=n;i++) a[i]=read();
	insert(s,1,k,0);
	for(int i=1;i<=n;i++){
		insert(i,min(n+1,i+m),1,a[i]);
		insert(i,i+1,k,0);
	}
	insert(n+1,t,k,0);
	zkw();
	printf("%d\n",ans);
	return 0;
}

  

posted @ 2018-08-16 07:59  zhangenming  阅读(170)  评论(0编辑  收藏  举报