【bzoj2083/Poi2010】Intelligence test——二分+贪心

Description

霸中智力测试机构的一项工作就是按照一定的规则删除一个序列的数字,得到一个确定的数列。Lyx很渴望成为霸中智力测试机构的主管,但是他在这个工作上做的并不好,俗话说熟能生巧,他打算做很多练习,所以他希望你写一个程序来快速判断他的答案是否正确。

Input

第一行为一个整数m(1<=m<=1000000)第二行包括m个用空格分开的整数ai(1<=ai<=1000000),组成了最初的序列,第三行为一个整数n(1<=n<=1000000),表示n个Lyx经过一系列删除得到的序列,每个序列两行,第一行给出长度L(1<=L<=m),然后下一行为L个由空格分开的整数bi(1<=bi<=1000000)。

Output

共n行,如果Lyx的序列确实是由最初的序列删除一些数得到,就输出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
 

 
题目大概就是询问某个序列是否是原序列的子序列。
可以用AC自动机写,当然也可以用二分+贪心的方法。
对于每个值为ai的数建一个vector存下标,每次询问都贪心的选择原序列中可选的值为ai的位置即可。
代码:
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 const int N=1e6+10;
 6 int n,m,L;
 7 std::vector<int>ve[N];
 8 int read(){
 9     int ans=0,f=1;char c=getchar();
10     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
11     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
12     return ans*f;
13 }
14 int main(){
15     m=read();
16     for(int i=1,a;i<=m;i++)a=read(),ve[a].push_back(i);
17     n=read();
18     while(n--){
19         L=read();int now=0,l,r;bool flag=0;
20         for(int i=1,a;i<=L;i++){
21             a=read();if(flag)continue;
22             l=0,r=ve[a].size()-1;
23             while(l<=r){
24                 int mid=(l+r)>>1;
25                 if(ve[a][mid]<now)l=mid+1;
26                 else r=mid-1;
27             }
28             if(l>=ve[a].size()){flag=1;continue;}
29             now=ve[a][l]+1;
30         }
31         if(flag)printf("NIE
");
32         else printf("TAK
");
33     }
34     return 0;
35 }
bzoj2083
原文地址:https://www.cnblogs.com/JKAI/p/7624760.html