BZOJ 3550 Vacation

http://www.lydsy.com/JudgeOnline/problem.php?id=3550

题意:有3N个数,你需要选出一些数,首先保证任意长度为N的区间中选出的数的个数<=K个,其次要保证选出的数的个数最大。

思路:和这题类似http://www.cnblogs.com/qzqzgfy/p/5612261.html

可以转换成不等式然后求费用流。

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstring>
 6 #define inf 0x7fffffff
 7 int tot,go[200005],next[200005],first[200005],flow[200005],cost[200005];
 8 int dis[200005],vis[200005],op[200005],edge[200005],from[200005],ans,a[200005];
 9 int n,K,S,T,c[200005];
10 int read(){
11     int t=0,f=1;char ch=getchar();
12     while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();}
13     while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
14     return t*f;
15 }
16 void insert(int x,int y,int z,int l){
17    tot++;
18    go[tot]=y;
19    next[tot]=first[x];
20    first[x]=tot;
21    flow[tot]=z;
22    cost[tot]=l;
23 }
24 void add(int x,int y,int z,int l){
25    insert(x,y,z,l);op[tot]=tot+1;
26    insert(y,x,0,-l);op[tot]=tot-1;
27 }
28 bool spfa(){
29    for (int i=S;i<=T;i++) dis[i]=0x3f3f3f3f,vis[i]=0;
30    int h=1,t=1;vis[S]=1;c[1]=S;dis[S]=0;
31    while (h<=t){
32        int now=c[h++];
33        for (int i=first[now];i;i=next[i]){
34              int pur=go[i];
35              if (dis[pur]>dis[now]+cost[i]&&flow[i]){
36                 dis[pur]=dis[now]+cost[i];
37                 from[pur]=now;
38                 edge[pur]=i;
39                 if (vis[pur]) continue;
40                 c[++t]=pur;
41                 vis[pur]=1;
42             }
43         }
44         vis[now]=0;
45     }
46     return dis[T]!=0x3f3f3f3f;
47 }
48 void updata(){
49     int mn=0x7fffffff;
50     for (int i=T;i!=S;i=from[i]){
51           mn=std::min(mn,flow[edge[i]]);
52     }
53     for (int i=T;i!=S;i=from[i]){
54           flow[edge[i]]-=mn;
55           flow[op[edge[i]]]+=mn;
56           ans+=mn*cost[edge[i]];
57     }
58 }
59 void mncostflow(){
60    ans=0;
61    while (spfa()) updata();
62    printf("%d\n",-ans);
63 }
64 int main(){
65     n=read();K=read();S=0;T=2*n+3;
66     for (int i=1;i<=3*n;i++)
67         a[i]=read();
68     for (int i=1;i<=2*n+1;i++)
69         add(i+1,i,inf,0);
70     add(1,T,K,0);
71     add(S,2*n+2,K,0);
72     for (int i=1;i<=n;i++)
73         add(i+1,1,1,-a[i]);
74     for (int i=n+1;i<=n+n;i++)
75         add(i+1,i+1-n,1,-a[i]);
76     for (int i=n+n+1;i<=n*3;i++)
77         add(2*n+2,i-n+1,1,-a[i]);
78     mncostflow();
79 }
时间: 2024-10-12 18:45:42

BZOJ 3550 Vacation的相关文章

BZOJ 3550 ONTAK2010 Vacation 单纯形

题目大意:给定一个长度为3n的区间,要求选一些数,且任意一段长度为n的区间内最多选k个数,求选择数的和的最大值 单纯形直接搞 注意一个数只能被选一次 因此要加上xi<=1这个约束条件 不明白3n还有k<=10是为何... #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define EPS 1

BZOJ 3550 [ONTAK2010]Vacation 线性规划

题意:链接 方法:线性规划 解析: 这是一道蛮简单的单纯性线性规划. 首先我们设Xi表示第i个数是否选择. 则显然 X1+X2+...+Xn<=k X2+X3...+Xn+1<=k - X2n+1+X2n+2+...+X3n<=k 其次0<=Xi<=1 并且我们要最大化∑3ni=1Ci?Xi 观察如上式子,显然为标准型线性规划. 单纯性出解即OK. 代码: #include <cstdio> #include <cstring> #include &l

【BZOJ】【3550】【ONTAK2010】Vacation

网络流/费用流 Orz太神犇了这题…… 我一开始想成跟Intervals那题一样了……每个数a[i]相当于覆盖了(a[i]-n,a[i]+n)这个区间……但是这样是错的!!随便就找出反例了……我居然还一直当正解…… 实际上刚刚那个思路还有一个问题:题目中的长度为N的区间指的是给的原序列!而不是权值的区间!题就理解错了…… 看了下zyf的题解,才明白过来,要用跟志愿者招募一样的方法来做:另外,志愿者招募时每种志愿者是有无限多名的,但这题中每个数只能选一次,所以边权为a[i]的边的流量不能是INF,

【BZOJ1283/3550】序列/[ONTAK2010]Vacation 最大费用流

[BZOJ1283]序列 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&

BZOJ3550: [ONTAK2010]Vacation

3550: [ONTAK2010]Vacation Time Limit: 10 Sec  Memory Limit: 96 MBSubmit: 91  Solved: 71[Submit][Status] Description 有3N个数,你需要选出一些数,首先保证任意长度为N的区间中选出的数的个数<=K个,其次要保证选出的数的个数最大. Input 第一行两个整数N,K.第二行有3N个整数. Output 一行一个整数表示答案. Sample Input 5 3 14 21 9 30 11

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3