Description
PTY进行IQ测试,测试的项目是判断一个序列是否是另外一个序列删除若干个数字之后得
到的,PTY 深知自己的IQ 低于sqrt(-1),所以他请来了智商超高的你来替他解决问题。
Input
第一行为一个整数n,第二行包括n个用空格分开的整数ai,组成了最初的序列,第三行为一个整数m,表示n个IQ测试询问的序列,每个序列两行,第一行给出长度 L(1<=L<=n),然后下一行为L 个由空格分开的整数bi。
Output
共m行,如果询问的序列确实是由最初的序列删除一些数得到,就输出TAK,否则输出NIE。
Sample Input
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
Sample Output
TAK
NIE
TAK
NIE
Data Constraint
对于30%的数据:n<=1000,m<=1000
对于100%的数据:1<=ai,bi<=1000000,ΣL<=1000000,n,m<=1000000
Solution
这题再一看很简单,维护两个指针即可,但是一看数据范围就吓个半死~
当我静下心来思考时,就发现没有想象中的那么恐怖。
注意到 ∑L≤106 ,于是考虑逐个逐个数列处理。
当处理到第i个数列时,将每一个元素在原数列中查找,当查找不到时则输出“NIE”;
怎样查找呢?——可以 O(logN) 查找。
开一个Vector,读入原数列时,将当前值所处的的位置 Push进当前值的Vector中,
查找即可在Vector中二分查找未匹配的位置中最前的那一个,之后更新已匹配位置即可。
这样的时间复杂度为 NlogN 级别,加上 读入输出优化 可以避免卡常!
Code
#include<cstdio>
#include<vector>
#define P(x) putchar(x)
using namespace std;
vector<int>f[1000001];
inline int read()
{
int data=0; char ch=0;
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
return data;
}
int main()
{
int n=read();
for(int i=1;i<=n;i++) f[read()].push_back(i);
int m=read();
while(m--)
{
int k=read(),last=0;
bool bz=true;
while(k--)
{
int x=read();
int l=0,r=f[x].size()-1;
if(r<0 || f[x][r]<=last)
{
bz=false;
while(k--) read();
break;
}
while(l<r)
{
int mid=(l+r)>>1;
if(f[x][mid]<=last) l=mid+1; else r=mid;
}
if(f[x][l]>last) last=f[x][l]; else
{
bz=false;
while(k--) read();
break;
}
}
if(bz) P('T'),P('A'),P('K'); else P('N'),P('I'),P('E');
P('\n');
}
return 0;
}