ZOJ_3297 Cookie Choice II(尺取)

Cookie Choice II

Time Limit: 4000 ms
Memory Limit: 32768 KB
Problem Description

As all you know, MM loves cookies very much and now she’s going to make another cookie choice!

There is a sequence of N cookies while there may be K different kinds of cookies.

MM wants to choose a continuous subsequence of cookies to eat (the subsequence may be empty), while for each kind of cookie, there are minimum and maximum numbers MM want to choose.

But DD wants to minimize the length of chosen continuous subsequence (for his poor wallet). You are to find the shortest continuous sequences that satisfy MM’s requirement.

Formally speaking, define the cookie sequence as C i C_i Ci ( 1 < = i < = N , 1 < = C i < = K 1<=i<=N, 1<=C_i<=K 1<=i<=N,1<=Ci<=K), where C i C_i Ci is the kind of the ithe cookie, and the chosen continuous subsequence has Mi cookies of kind i. Mi must satisfy A i < = M i < = B i A_i<=M_i<=B_i Ai<=Mi<=Bi. While A i A_i Ai and B i B_i Bi are given miminum and maximum numbers of kind i to choose.

Input

About 20 test cases, seperated by blank line.

First line of each case is two integers N N N ( 1 < = N < = 400000 1<=N<=400000 1<=N<=400000) and K K K ( 1 < = K < 2048 1<=K<2048 1<=K<2048). The second line is N numbers of sequence C. The following K lines, the ith line has two numbers A i A_i Ai and B i B_i Bi.

All numbers are integers.

Output

For each test case, output the minimum length of chosen continuous subsequence.

If no answer, output -1.

Sample Input

5 2
1 2 2 2 1
2 4
1 3

7 2
1 2 1 2 1 2 1
3 4
0 1

Sample Output

5
-1

题意

有一个包含n个数的序列,序列中的每个数都是 [ 1 , k ] ( 1 ≤ k ≤ 2048 ) [1,k](1\le k\le2048) [1,k](1k2048)的数字。要求选出一段连续的子序列,使 [ 1 , k ] [1,k] [1,k]中的每个数字出现的次数 n u m i num_i numi满足 a i ≤ n u m i ≤ b i a_i \le num_i \le b_i ainumibi。求满足条件的最短子序列的长度。

题解:

尺取法。每次数字出现的次数需要满足上界和下界,所有的子序列都必须达到下界,所以在尺取时找到满足下界的最短长度。同时在统计出现次数时,记录有多少个数超出了上界。如果有超出上界的话,则该段区间不成立。
ai貌似可以为负数。

#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-6
 
using namespace std;
typedef long long LL;   
typedef pair<int, int> P;
const int maxn = 500100;
const int mod = 1000000007;
int a[maxn], b[3000], c[3000], d[3000];

int main()
{
    int n, k, i, j, l, r, num1, num2, sig;
    while(scanf("%d %d", &n, &k)!=EOF)
    {
        memset(d, 0, sizeof(d));
        num1 = num2 = sig = 0;
        int ans = INF;
        for(i=0;i<n;i++)
            scanf("%d", &a[i]);
        for(i=1;i<=k;i++){
            scanf("%d %d", &b[i], &c[i]);
            //貌似b[i]可能为负数,改为b[i]==0会WA
            if(b[i] <= 0)num1++;
        }
        if( num1 == k){
            printf("0\n");
            continue;
        }
        l = 0, r = 0;
        while(l<n){
            while(r<n && num1<k){
                j = a[r];
                d[j]++;
                if(d[j] == b[j])num1++;
                if(d[j] == c[j]+1)num2++;
                r++;
            }
            if(num1 == k && num2 == 0)ans = min(ans, r-l);
            j = a[l];
            if(d[j] == b[j])num1--;
            if(d[j] == c[j]+1)num2--;
            d[j]--;
            l++;
        }
        if(ans == INF)printf("-1\n");
        else printf("%d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值