IQ測試(jzoj 5048)

IQ測試

jzoj 5048

題目大意

給出一個序列a,然後有m個詢問,每個詢問給出一個序列,問這個序列是否可以由序列a刪掉一些數得到的

輸入樣例

7
1 5 4 5 7 8 6
4
5
1 5 5 8 6
3
2 2 2
3
5 7 8
4
1 5 7 4

輸出樣例

TAK
NIE
TAK
NIE

數據範圍

對於30%的數據:n1000,m1000n\leqslant 1000,m\leqslant 1000
對於100%的數據:1ai,bi1000000L1000000n,m10000001\leqslant ai,bi\leqslant 1000000,\sum L\leqslant 1000000,n,m\leqslant 1000000

解題思路

數據有1000000這麼大,那應該就是ono(n)左右的
數據寫到L1000000\sum L\leqslant 1000000,那他就一定有他的作用
我們把所有序列放在一起看
我們可以枚舉序列a,對於每一個數
如果和某個序列的指針所指向的數字相同,那我們就把這個序列的指針指向下一位,就是當前數字已找到
如果一個序列可以按順序在序列a中找到它的每一個數,那它就是符合的
但如果每一個序列都搜一遍的話就會TLETLE
我們可以用一個數組來記錄指針指向某個數字的序列有哪些

代碼

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n, m, w, g, a[1000010], s[1000010];
vector<int>h[1000010], b[1000010];//要用vector才能即不超時又不超內存
int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i)
		scanf("%d", &a[i]);
	scanf("%d", &m);
	for (int i = 1; i <= m; ++i)
	{
		scanf("%d", &w);
		for (int j = 1; j <= w; ++j)
		{
			scanf("%d", &g);
			b[i].push_back(g);
		}
		h[b[i].front()].push_back(i);//第一個數
	}
	for (int i = 1; i <= n; ++i)
	{
		w = h[a[i]].size();//指針指向a[i]序列數
		for (int j = 0; j < w; ++j)
		{
			g = h[a[i]][j];//第幾個序列
			s[g]++;//指針加一
			if (s[g] < b[g].size()) h[b[g][s[g]]].push_back(g);//沒有遍歷完,再指向下一個
		}
		h[a[i]].erase(h[a[i]].begin(), h[a[i]].begin() + w);//刪掉原有的
	}
	for (int i = 1; i <= m; ++i)
		if (s[i] >= b[i].size()) printf("TAK\n");//遍歷完的
		else printf("NIE\n");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章