2020牛客暑期多校训练营(第六场)K.K-Bag(思维,离散化)

题目链接

思路:

首先判断每一位置之后有多少个不重复的数字,然后再枚举所有可能的第一个断点的位置,遍历判断从这个断点开始之后的每一个断点是否可以成为一个排列,因为k=1e9,所以我们要用到离散化。

代码:

#include
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N=1e5+7;
const double eps=1e-8;
const int mod=1e9+7;
const int inf=0x7fffffff;
const double pi=3.1415926;
int a[510000],b[510000],len[510000],pre[510000];
signed main()
{
    IOS;
    int t;
	cin>>t;
	while(t--)
    {
		cin>>n>>k;
		int ok=1;
		for(int i=1;i<=n;i++)
        {
			cin>>a[i];
			b[i]=a[i];
			if(a[i]>k||a[i]<0)
            {
                ok=0;
            }
		}
		if(!ok)
        {
			cout<<"NO"<<endl;
			continue;
		}
		sort(b+1,b+n+1);
		int cnt=unique(b+1,b+n+1)-b-1;//去重
		for(int i=1;i<=n;i++)//离散化
		{
		    a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
		}
		int p=1;
		for(int i=1;i<=n;i++)//判断从i开始之后连续且不重复的数字有多少位
        {
			while(!pre[a[p]]&&p<=n)
            {
                pre[a[p]]++;
                p++;
            }
			pre[a[i]]--;
			len[i]=p-i;
		}
		int sc=0;
		for(int st=1;st<=min(k,len[1]+1);st++)
		{
			bool flag=true;
			for(int i=st;i<=n;i+=k)
			{
				if(i+len[i]>=n+1)
				{
				    continue;
				}
				else if(len[i]!=k)
                {
					flag=false;
					break;
				}
			}
			if(flag==true)
            {
				sc=1;
				break;
			}
		}
		cout<<(sc?"YES":"NO")<<endl;
	}
	return 0;
}

你可能感兴趣的:(思维,离散化)