bzoj 2083 Intelligence test —— 思路+vector

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2083

先把所有子序列都存下来,总长度应该有限制,所以用 vector 存;

要做到 O(n),就得遍历原序列的同时匹配所有子序列;

注意到,遍历原序列,一个位置上只有一个值(当然啦);

所以考虑这一个值能否推进子序列的匹配,就需要知道每个子序列下一步需要的值是多少;

再换个角度,在每个值上挂一个 vector,存需要这个值的子序列有哪些;

然后遍历到这个位置,就把它的值上挂的所有子序列的匹配都推进1步,匹配完就是可行的;

思路很好的一道题!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
int const xn=1e6+5;
int m,n,a[xn],l[xn];
bool ok[xn];
struct N{int x,y;};
vector<int>b[xn];
vector<N>v[xn],sta;
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return f?ret:-ret;
}
int main()
{
  m=rd();
  for(int i=1;i<=m;i++)a[i]=rd();
  n=rd();
  for(int i=1;i<=n;i++)
    {
      l[i]=rd();
      for(int j=1,x;j<=l[i];j++)x=rd(),b[i].pb(x);
      int y=b[i][0]; v[y].pb((N){i,1});
    }
  for(int i=1;i<=m;i++)
    {
      int y=a[i]; sta.clear();
      for(int j=0;j<v[y].size();j++)
    {
      N t=v[y][j];
      if(t.y==l[t.x])ok[t.x]=1;
      else sta.pb((N){t.x,t.y+1});
    }
      v[y].clear();
      for(int j=0;j<sta.size();j++)
    {
      N t=sta[j];
      v[b[t.x][t.y-1]].pb(t);//b:0~l-1
    }
    }
  for(int i=1;i<=n;i++)
    {
      if(ok[i])puts("TAK");
      else puts("NIE");
    }
  return 0;
}
原文地址:https://www.cnblogs.com/Zinn/p/9809449.html