Codeforces 1142B(倍增)
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 }