[BZOJ] 2083: [Poi2010]Intelligence test

2083: [Poi2010]Intelligence test

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 597  Solved: 311
[Submit][Status][Discuss]

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

HINT

 

Source

Analysis

据说这是范围暴露算法典型,,,

对的

对原初序列里每一个数字建一个地址表

记录每个数字出现的位置

然后录入待查找序列

对待查找里的每个数字相应的地址表进行二分

看会不会有矛盾

如果不会就....

Bi的范围有点问题,不要压线开vector

Code

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<vector>
 4 using namespace std;
 5 
 6 vector<int> pos_list[101010];
 7 
 8 int find(int val,int pos){
 9     if(!pos_list[val].size()) return -1;
10     int L = 0,R = pos_list[val].size()-1;
11     while(L < R){
12         int mid = (L+R)/2;
13         if(pos_list[val][mid] <= pos) L = mid+1;
14         else R = mid;
15     }return pos_list[val][L];
16 }
17 
18 int n,cnt,m,T;
19 
20 int main(){
21     scanf("%d",&n);
22     
23     for(int i = 1;i <= n;i++){
24         scanf("%d",&cnt);
25         pos_list[cnt].push_back(i);
26     }
27     
28     scanf("%d",&m);
29     while(m--){
30         scanf("%d",&T);
31         
32         int last = 0;
33         for(int i = 1;i <= T;i++){
34             scanf("%d",&cnt);
35             if(last == -1) continue;
36             int pos = find(cnt,last);
37             if(pos > last) last = pos;
38             else{
39                 last = -1;
40             }
41         }if(last < 0) printf("NIE
");
42         else printf("TAK
");
43     }
44     
45     return 0;
46 }
=w=
原文地址:https://www.cnblogs.com/Chorolop/p/7660900.html