1. 程式人生 > >ZOJ Monthly, January 2019 Little Sub and Isomorphism Sequences 【離線離散化 + set + multiset】

ZOJ Monthly, January 2019 Little Sub and Isomorphism Sequences 【離線離散化 + set + multiset】

插入 tdi -- for each input clear pre cati when

傳送門:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5868

Little Sub and Isomorphism Sequences

Time Limit: 3 Seconds Memory Limit: 65536 KB

Little Sub has a sequence . Now he has a problem for you.

Two sequences of length and of length are considered isomorphic when they meet all the following two conditions:

  1. ;
  2. Define as the number of times integer occur in sequence . For each integer in , always holds.

Now we have operations for . and there are two kinds of operations:

  • 1 x y: Change to (, );
  • 2: Query for the greatest () that there exist two integers and () and is isomorphic with . Specially, if there is no such , please output "-1" (without quotes) instead.

Input

There are multiple test cases. The first line of the input contains an integer (), indicating the number of test cases. For each test case:

The first line ontains two integers .

The second line contains integers ().

In the following lines, each line contains one operation. The format is described above.

Output

For each operation 2, output one line containing the answer.

Sample Input

1
3 5
1 2 3
2
1 3 2
2
1 1 2
2

Sample Output

-1
1
2

題意概括:

給出 一個長度為 N 的序列, 和 M 次操作.

有兩種操作:

1 id y : 把序列中第 id 個位置的值 修改成 y

2 : 查詢這個序列中能滿足兩個子串“相同”的最大長度。

兩個子串相同的條件:子串的數字種類和每種種類的數量相同,當然兩個子串的起點不同(理所當然,否則這道題就沒意義了)。

解題思路:

很明顯就是維護每種 相同的值的 下標(位置)的 最大差值。

因為除了兩端的值,中間公共部分 無論是數量還是種類肯定相同。

那麽問題就轉換成了如何維護每種值 value 的位置最大差值。

用 set 存每種 value 的下標,最多需要 20w個(最壞的情況就是每次操作都是插入新的值)

用 multiset 維護 最大差值。

值 val 的範圍是 【1, 1e9】,需要離散化。

在線 map 離散化 RE。

離線 lower_bound() AC。

AC code:

 1 #include <set>
 2 #include <map>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 #define INF 0x3f3f3f3f
 8 #define LL long long
 9 using namespace std;
10 const int MAXN = 2e5+10;
11 const int MAXM = 2e5+10;
12 int a[MAXN];      //存實際序列
13 int b[MAXN];      //存所有序列包括原序列的值和修改的值,用於離散化
14 int c[MAXN];      //存操作
15 int x[MAXN];      //存修改的下標
16 int y[MAXN];      //存修改的值
17 set<int>ss[MAXM];   ///維護每一種值的起點和終點
18 multiset<int>ans;   ///維護兩點距離差
19 //map<int, int>mmp;
20 int N, M;
21 
22 int main()
23 {
24     int cnt = 0;
25     int T_case;
26     scanf("%d", &T_case);
27         while(T_case--){
28 
29             int cnt = 0;
30             ans.clear();
31             scanf("%d %d", &N, &M);
32             for(int i = 1; i <= N; i++){
33                 scanf("%d", &a[i]);
34                 b[++cnt] = a[i];
35             }
36 
37             for(int i = 1; i <= M; i++){
38                 scanf("%d", &c[i]);
39                 if(c[i] == 1){
40                     scanf("%d %d",&x[i], &y[i]);
41                     b[++cnt] = y[i];
42                 }
43             }
44             sort(b+1, b+1+cnt);
45             cnt = unique(b+1, b+cnt+1)-(b+1);   ///離散化後的數據總量
46 
47             for(int i = 1; i <= cnt; i++){      ///初始化
48                 ss[i].clear();
49             }
50 
51             for(int i = 1; i <= N; i++){
52                 a[i] = lower_bound(b+1, b+cnt+1, a[i])-b;   ///對原序列的值進行離散化
53                 ss[a[i]].insert(i);
54             }
55 
56             for(int i = 1; i <= cnt; i++){
57                 if(!ss[i].empty()) ans.insert(*--ss[i].end() - *ss[i].begin()); ///初始化兩點距離差
58             }
59 
60             for(int i = 1; i <= M; i++){
61                 if(c[i] == 1){                              ///刪除操作
62                     int no = a[x[i]];
63                     ans.erase(ans.find( *--ss[no].end()-*ss[no].begin()) );
64                     ss[no].erase(ss[no].find(x[i]));
65                     if(!ss[no].empty()) ans.insert(*--ss[no].end()-*ss[no].begin());
66 
67 
68                     y[i] = lower_bound(b+1, b+cnt+1, y[i])-b;       ///增加操作
69                     a[x[i]] = y[i];
70                     no = y[i];
71                     if(!ss[no].empty()) ans.erase(ans.find( *--ss[no].end()-*ss[no].begin()) );
72                     ss[no].insert(x[i]);
73                     ans.insert(*--ss[no].end()-*ss[no].begin());
74                 }
75                 else{
76                     int res = -1;
77                     if(!ans.empty()){
78                         res = *--ans.end();
79                     }
80                     if(res == 0) res = -1;
81                     printf("%d\n", res);
82                 }
83             }
84 
85 
86         }
87     return 0;
88 }

ZOJ Monthly, January 2019 Little Sub and Isomorphism Sequences 【離線離散化 + set + multiset】