Http://acm.zju.edu.cn/onlinejudge/showProblem.do? Problemcode = 3633.
Two solutions:
In my own solution, because the 31 side of the visit array 10 was too large, we first discretization the given number, then, the subscript edge of each number in the range and its array is connected.
When querying, traverse the query range. For each number, if the edge of the number is marked before this number and within the query range, output this number.
* ********* At the beginning, OK is converted into lower case, wa to vomit blood ....
# Include <iostream> # include <string. h> # include <algorithm> # include <vector> # include <stdio. h> # include <stdlib. h ># define maxn 500100 using namespace STD; struct node0 {long key; int ID;} node [maxn]; vector <int> line [maxn]; int N; int m; long number [maxn]; bool CMP1 (struct node0 A, struct node0 B) {return. key <B. key;} bool cmp2 (struct node0 A, struct node0 B) {return. ID <B. ID;} int main () {long Max; while (CIN> N) {memset (number, 0, sizeof (number); memset (node, 0, sizeof (node); For (INT I = 0; I <= N; I ++) line [I]. clear (); For (INT I = 0; I <n; I ++) {CIN> node [I]. key; number [I] = node [I]. key; node [I]. id = I;} Sort (node, node + N, CMP1); // sort by size
// Discretization int temp = node [0]. key; node [0]. key = 0; line [0]. push_back (node [0]. ID); For (INT I = 1; I <n; I ++) {If (node [I]. key = temp) node [I]. key = node [I-1]. key, line [node [I]. key]. push_back (node [I]. ID); // EDGE connection else temp = node [I]. key, node [I]. key = node [I-1]. key + 1, line [node [I]. key]. push_back (node [I]. ID); // edge} Sort (node, node + N, cmp2); // sort by subscript. Cin> m; while (M --) {int St, en; int flage = 0; CIN> st> en; int ID; for (INT I = en-1; I> = ST-1; I --) {for (Int J = 0; j <line [node [I]. key]. size (); j ++) {If (line [node [I]. key] [J]> = I + 1 & line [node [I]. key] [J] <= en-1) // access if (line [node [I]. key] [J]! = I) {flage = 1; id = I; break ;}} if (flage) break;} If (flage) cout <number [ID] <Endl; else cout <"OK" <Endl ;}cout <Endl ;}return 0 ;}
The practice circulating on the Internet is the line segment tree. When I thought about it, I did not think of it at the time. For each subscript of the number equal to that obtained before this number. The maxd attribute is added to the online segment tree, which indicates the number of all numbers in the current range, the subscript equal to this number and before this number is greater than that of other numbers in this range.
Then you can determine whether the returned subscript is within the range.
# Include <iostream> # Include <Stdio. h> # Include < String . H> # Include <Algorithm> # Include <Vector> # Include <Map> # Define Maxn 500100 Using Namespace STD; Int Visit [ 100 ]; Struct Node0 { Int L; Int R; Int Maxd;} node [maxn]; Int Dis [maxn]; Int Number [maxn]; Void Build ( Int Root, Int L, Int R) {node [root]. L = L; node [root]. r = R; If (L = R) {node [root]. maxd = Dis [l]; Return ;} Int Mid = (L + r)> 1 ; Build (Root < 1 , L, mid); Build (Root < 1 | 1 , Mid + 1 , R); node [root]. maxd = Max (node [root < 1 ]. Maxd, node [root < 1 | 1 ]. Maxd ); Return ;} Int Query ( Int Root, Int L, Int R ){ // Cout <root <"" <node [root]. L <"" <node [root]. r <"" <node [root]. maxd <Endl; If (Node [root]. L = L & node [root]. r = R) Return Node [root]. maxd; // If (L = r) return 0; Int Mid = (node [root]. L + node [root]. R)>1 ; If (R <= Mid) Return Query (root < 1 , L, R ); Else If (L> Mid) Return Query (root < 1 | 1 , L, R ); Else { Return Max (query (root < 1 , L, mid), query (root < 1 | 1 , Mid + 1 , R ));}} Void Output ( Int Root ){ If (! Visit [root]); cout <Node [root]. L < " " <Node [root]. r < " " <Node [root]. maxd < " " <Root < Endl; visit [root] = 1 ; If (Node [root]. L = node [root]. R) Return ; Output (Root < 1 ); Output (Root < 1 |1 );} Int Main (){ Int N, m; Int St, en; While (CIN> N) {Map < Long Long , Int > V; For ( Int I = 1 ; I <= N; I ++ ) {CIN > Number [I]; DIS [I] = V [number [I]; V [number [I] = I;} build ( 1 , 1 , N ); // Output (1 ); Cin> M; While (M -- ) {CIN >>> St>En; Int Temp = query ( 1 , St, en ); If (Temp> = sT & temp <= En) cout <Number [temp] < Endl; Else Cout < " OK " < Endl;} cout < Endl ;} Return 0 ;}
The line segment tree is faster than its own.