1. 程式人生 > >CF 1142B(倍增)

CF 1142B(倍增)

code span pre nbsp scan max div scanf pos

1.先預處理出在循環中某數前面的數是誰。

2.讀入a數列時貪心選取最晚的父親。

3.鏈上倍增預處理二進制祖先。

4.對於每個位置,預處理第n-1個祖先位置最早要從哪裏開始,技巧上再順手與前一位的最早位置取max,盡量縮小區間。

5.查詢已經可做。

 1 const int maxn = 2e5 + 5;
 2 int n, m, q, permu[maxn], pre[maxn], a[maxn], f[maxn][25], late[maxn], L[maxn];
 3 
 4 int Find(int pos, int n) {
 5     irep(i, 20
, 0) 6 if (n >= 1 << i) { 7 n -= 1 << i; 8 pos = f[pos][i]; 9 } 10 return pos; 11 } 12 13 int main() { 14 scanf("%d%d%d", &n, &m, &q); 15 16 rep(i, 0, n - 1) 17 scanf("%d", &permu[i]); 18 rep(i, 0
, n - 1) 19 pre[permu[i]] = permu[(i - 1 + n) % n]; 20 21 rep(i, 1, m) { 22 scanf("%d", &a[i]); 23 f[i][0] = late[pre[a[i]]]; 24 late[a[i]] = i; 25 } 26 rep(i, 1, 20) 27 rep(j, 1, m) 28 f[j][i] = f[f[j][i - 1]][i - 1];
29 rep(i, 1, m) 30 L[i] = max(Find(i, n - 1), L[i - 1]); 31 32 while (q--) { 33 int l, r; 34 scanf("%d %d", &l, &r); 35 printf("%d", L[r] >= l); 36 } 37 38 return 0; 39 }

CF 1142B(倍增)