Question link: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action? Id = 47319
For a given sequence, it is required to determine a subsequence, ① so that all values in the subsequence can be divisible by one of the values, ② The subsequence range is as large as possible (R-l is as large as possible ).
Solution:
For requirement 1, it is not difficult to find that only min (L, R) = gcd (L, R) is required. GCD is l, Min is l, and r is the minimum value.
For requirement 2, the traditional approach is to enumerate R-l from large to small, and determine a (L, R) range each time until it is feasible. Complexity O (N ^ 2) Tie Ding TLE.
Since the R-l value is ordered, binary is used. First, enumerate the middle value of R-l. If yes, consider it to the right to see if there is a larger value. Otherwise, go to the left.
Of course, this question is more difficult than that. Even though it uses binary classification, only the enumeration complexity is O (nlogn), plus the query orz.
At first, I used the line segment tree to complete rmq and GCD query. The complexity O (N * logn). When CF ran to test10, It would be TLE.
After reading the problem solution, we found that the st algorithm should be used to complete rmq and GCD in O (1) time. This is also the first time that I met the st algorithm. I saw Liu rujia's fried chicken concise, St, And I got down.
# Include "cstdio" # include "iostream" # include "vector" # include "algorithm" # include "math. H "# include" cstring "using namespace STD; # define lson L, mid, root <1 # define rson Mid + 1, R, root <1 | 1 # define maxns 3*100005 # define maxp 20 template <class T> inline bool read (T & RET) {char C; int SGN; if (C = getchar (), c = EOF) return 0; // EOF while (C! = '-' & (C <'0' | C> '9') c = getchar (); SGN = (C = '-')? -1:1; ret = (C = '-')? 0 :( C-'0'); While (C = getchar (), c> = '0' & C <= '9 ') ret = RET * 10 + (c-'0'); RET * = SGN; return 1;} int gcd (int A, int B) {If (B! = 0) return gcd (B, A % B); else return a;} int rmq [maxn] [maxp], gcd [maxn] [maxp], Val [maxn], n, CNT, range; vector <int> ans; void ST () {for (INT I = 1; I <= N; I ++) rmq [I] [0] = GCD [I] [0] = Val [I]; for (Int J = 1; (1 <j) <= N; j ++) for (INT I = 1; I + (1 <j)-1 <= N; I ++) {rmq [I] [J] = min (rmq [I] [J-1], rmq [I + (1 <(J-1)] [J-1]); GCD [I] [J] = gcd (GCD [I] [J-1], gcd [I + (1 <(J-1)] [J-1]);} bool query (int l, int R) {int K = 0; while (1 <(k + 1) <= R-L + 1) K ++; int A = min (rmq [l] [K], rmq [R-(1 <k) + 1] [k]); int B = gcd (GCD [l] [K], gcd [R-(1 <k) + 1] [k]); if (a = B) return true; else return false;} bool judge (INT v) // enumerated R-l {int cc = 0; vector <int> tt; For (INT I = 1; V + I <= N; I ++) {If (query (I, I + V) // L = I, r = I + V; {CC ++; TT. push_back (I) ;}}if (CC> 0) {ans = tt; CNT = cc; range = V; return true;} return false;} int main () {memset (rmq, 1, sizeof (rmq); memset (GCD, 1, sizeof (GCD); read (n); For (INT I = 1; I <= N; I ++) read (Val [I]); ST (); int L = 0, r = n-1, mid; while (L <= r) // binary {mid = (L + r)> 1; if (Judge (MID) L = Mid + 1; else r = mid-1 ;} printf ("% d \ n", CNT, range); For (INT I = 0; I <ans. size (); I ++) {if (I> 0) printf (""); printf ("% d", ANS [I]);}; printf ("\ n ");}
2808336 |
Neopenx |
Codeforces 359d |
Accepted |
51924 KB |
327 MS |
Gnu c ++ 4.6 |
1976 B |
2014-10-03 14:55:49 |
|
Codeforces 359d (number theory + binary + st algorithm)