poj 2189/3061 贪心(找连续的羊圈/连续子序列之和大于limit的最短序列)

题意:已知一行羊圈两两相连,中间由一个栅栏分开。给栅栏编号1-n,那么一共有n-1个羊圈。给定m个羊所在的位置,比如一个羊在x,那么表示他在x和x+1所围住的羊圈中。再给定一个常数c,求最大的连续区间,使得其中的羊总数不超过c。

思路:贪心即可。设两个游标i和j,扫一遍。相当于求固定起点i能够符合条件的最长的区间。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s))
#define N 1005
int n,m,c;
int s[N];
int main(){
    int i,j,x,res,num;
    scanf("%d %d %d",&m,&n,&c);
    clr(s, 0);
    for(i = 0;i<m;i++){
        scanf("%d",&x);
        s[x]++;
    }
    res = num = 0;
    for(i = j = 1;i<n;i++){
        num -= s[i-1];
        while(num <= c && j<n){
            num += s[j];
            j++;
        }
        res = max(res,j-i-1);
        if(j == n){
            if(num <= c)//忘了判断这个wa了一次
                res = max(res,j-i);
            break;
        }
    }
    printf("%d\n",res);
    return 0;
}


poj3061题意:求一个子序列的长度,这个子序列之和必须大于指定的一个值limit,且必须长度最小,求出这个序列的最小长度。

思路:同上,设置两个游标,从左到右扫一遍O(n)即可。如果预处理求出前n项和数组,在之上处理会更方便。

#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s));
#define N 100005
int s[N],n,m,T;
int main(){
    scanf("%d",&T);
    while(T--){
        int i,j,res=INF,now = 0;
        scanf("%d %d",&n,&m);
        for(i = 1;i<=n;i++)
            scanf("%d",&s[i]);
        for(i = 1,j = 0;j<=n;){
            while(now<m && j<n)
                now += s[++j];
            if(now<m && j>=n)
                break;
            res = min(res,j-i+1);
            while(now >= m && i<j)
                now -= s[i++];
            if(now>=m && i==j){
                res = 1;
                break;
            }
            res = min(res,j-i+2);
        }
        if(res == INF)
            printf("0\n");
        else
            printf("%d\n",res);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值