【C++竞赛 A】xxx的项链

来源:互联网 发布:saber软件正版价格 编辑:程序博客网 时间:2024/06/06 06:16

时间限制:2s 内存限制:64MB
问题描述
xxx有一个长度为n的宝石链,宝石有m种不同的颜色。xxx想截取其中连续的一段做一个项链。为了让项链更漂亮,xxx希望项链中的宝石包含所有颜色。
输入描述
第一行一个整数T(1≤T≤10)表示数据组数。
对于每组数据第一行两个整数n(1≤n≤〖10〗^5),m(1≤m≤30)
第二行n个整数C_1,C_2,…,C_n (0≤C_im)表示宝石链上每个宝石的颜色
输出描述
对于每组数据输出一行:一个整数,如果存在满足条件的方案,输出满足条件的最短长度,否则输出-1。
输入样例
2
4 3
0 1 2 0
4 3
0 1 1 0
输出样例
3
-1
样例解释
样例一: 截取[0 1 2],[1 2 0],[0 1 2 0]均满足条件,因此输出3
样例二: 没有满足条件的,输出-1

【题目链接】:
【题解】

枚举区间的左端点i,然后二分右端点;
用前缀和来记录到某个位置所有的颜色的贝壳的拥有情况;
右端点减去左端点的拥有情况就是中间的拥有情况;

【完整代码】

#include <bits/stdc++.h>#define rep1(i,a,b) for (int i = a;i <= b;i++)using namespace std;#define pb push_back;const int MAXN = 1e5+10;int n,q,m;int pre[MAXN][34],temp[34];bool ok(int l,int r){    int cnt = m;    rep1(i,0,m-1)    {        temp[i] = pre[r][i]-pre[l-1][i];        if (temp[i]==0)        {            cnt--;            return false;        }    }    if (cnt==m)        return true;    else        return false;}int main(){    //freopen("D:\\rush.txt","r",stdin);    int T;    scanf("%d",&T);    while (T--)    {        int ans = 21e8;        memset(pre,0,sizeof(pre));        scanf("%d%d",&n,&m);        rep1(i,1,n)        {            int x;            scanf("%d",&x);            pre[i][x]++;            for (int j = 0;j<=m-1;j++)                pre[i][j] += pre[i-1][j];        }        rep1(i,1,n)        {            int l = i,r = n,ans1=-1;            while (l<=r)            {                int m = (l+r)>>1;                if (ok(i,m))                    ans1=m,r = m-1;                else                    l = m+1;            }            if (ans1!=-1)                ans = min(ans,ans1-i+1);        }        if (ans==21e8)            puts("-1");        else            printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击