题意:有k种金属,需要用s个金属构造一个阵法(金属可能重复),
然后一条河,每一米都有一种且一个金属,问从任意一个点开始能否找到满足阵法要求的金属,如果能够满足,输出走的最少步数,否则输出DragonXie
题目
解决:
其实就是从某个点出发,往后走,走最短步数,拿到满足题目要求的金属数量和种类(可能拿的多,如你需要1,2,3金属,河上面是1,2,4,3,你就需要走4步,因为从1开始走,想拿3必须走4;如果你需要1,2,3金属,河上是1,1,2,4,3那么你是从第二个1开始走。)
拿一个队列放在这条河上移动,如果是阵法要求的金属就加入队列,当现在加入的那个金属和头队列一样,且现在这种金属是多于阵法要求的数量的,就把头队列那个金属pop掉,如果某次加入某个金属使得队列中的金属种类和数量>=阵法的要求,就记录下这次从这个点出发往后走过的步数,每次取min就好了。
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=3e6+9;
struct node
{
int pos,data;//pos记录金属的位置,data记录是哪种金属
};
queue<node>que;//代表我手里拿着的金属
set<int>se;//记录我所需要的金属的种类
int arr[N];//存河上的金属
int vis[N]; //记录我现在需要的每种金属的数量,可能为负数,代表我手里这种金属比阵法要求的多
int s,k,len;
int tol,ans;//tol形成阵法所需要的金属个数,ans是每次队列中的金属满足阵法的要求,对每次走过的距离取min
int flag;//判断是否某次可以满足阵法要求,flag为0是不可能形成
void Delete()
{
while(!que.empty())
{
node q=que.front();
if(vis[q.data]<0)//如果头队列的那种金属目前是多余阵法的要求的,就删除
{ //一直循环到某个金属不多为止
vis[q.data]++;
que.pop();
}
else break;
}
}
void judge(int r)
{
if(tol==s) //如果队列中的金属个数满足阵法要求
{
flag=1;
int l=que.front().pos; //l是我从哪个位置开始走
ans=min(ans,r-l+1); //走的距离
vis[que.front().data]++;//这个时候把头队列这个金属给扔掉,破坏这次形成的阵法,准备开始下一次,看是否有更短的步数
que.pop();
tol--; //经过上面那个函数的while循环,这个头队列一定是必须的金属,删掉后tol--
Delete();//删掉头队列后,头队列后面的金属的数量可能是多余的
}
}
void solve()
{
ans=inf; //先开最大
scanf("%d%d",&k,&s);
for(int i=0; i<s; i++)
{
int data;
scanf("%d",&data);
vis[data]++; //每种金属需要多少个,为0的时候是已经够了,负数的时候是你多拿了
se.insert(data); //记录需要的种类
}
scanf("%d",&len);
for(int i=0; i<len; i++)
{
int data;
scanf("%d",&data);
arr[i+1]=data;
}
for(int i=1; i<=len; i++)
{
if(se.count(arr[i])>0)//如果这种金属是阵法要求的,就加入队列
{
node q;
q.pos=i;
q.data=arr[i];
que.push(q);
vis[arr[i]]--;//这种金属减去一,代表我需要的少一个,可能为负数,代表我现在手里的这种金属是多的
if(vis[arr[i]]>=0)tol++;//>=0是因为我加入队列的金属,是我现在阵法必须要的,而不是多余的,那么tol++
Delete();//删除我手里多余的金属,从头开始删
judge(i); //判断这个时候队列中的金属是否满足阵法的要求,i是加入最后一个金属的位置。
}
}
if(flag==1)printf("%d\n",ans);
else printf("DragonXie\n");
}
int main()
{
solve();
return 0;
}