题目: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; }