Solution 1 Mo's Algorithm & Linked List
不会。。果断莫队
当插入一个数的时候,如果用set维护前驱后继,然后结果是:$O((n + m)\sqrt{n}\log n)$,没救的,卡不过去。
但是感觉原序列不会改变,使用set维护很浪费。
考虑链表,链表上的每个数的后继是这个数的后继。
考虑可以通过排序提前得到大小关系,不断从链表中删数就能得到它在剩下的区间内的前后继。如果询问在同一个块内直接暴力。否则把答案分成三部分。
- 两个数都在当前块外,先从小到大加入剩下的所有数,从右到左删掉它们,再从左到右不断加入它们,然后就能得到所有前缀的答案。
- 两个数都在当前块内,处理出所有后缀的答案,做法类似。
- 一个在当前块内,一个在块外,移动右指针的时候让块内的所有数在链表内,查询的时候删掉再加入。
Code
1 /** 2 * Codeforces 3 * Problem#765F 4 * Accepted 5 * Time: 1309ms 6 * Memory: 9400k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 #define pii pair<int, int> 13 #define fi first 14 #define sc second 15 16 const int cs = 350; 17 const signed int inf = (signed) (~0u >> 1); 18 19 typedef class Query { 20 public: 21 int l, r, lid, rid, id, res; 22 23 boolean operator < (Query b) const { 24 if (lid != b.lid) return lid < b.lid; 25 return r < b.r; 26 } 27 }Query; 28 29 int n, m; 30 int *ar; 31 pii *cr; 32 int *pre, *suf, *L; 33 Query *qs; 34 35 inline void init() { 36 scanf("%d", &n); 37 ar = new int[(n + 1)]; 38 cr = new pii[(n + 1)]; 39 pre = new int[(n + 2)]; 40 suf = new int[(n + 2)]; 41 L = new int[(n + 1)]; 42 for (int i = 1; i <= n; i++) 43 scanf("%d", ar + i), cr[i].fi = ar[i], cr[i].sc = i; 44 scanf("%d", &m); 45 qs = new Query[(m + 1)]; 46 for (int i = 1; i <= m; i++) { 47 scanf("%d%d", &qs[i].l, &qs[i].r); 48 qs[i].lid = (qs[i].l - 1) / cs, qs[i].rid = (qs[i].r - 1) / cs; 49 qs[i].id = i; 50 } 51 } 52 53 void add(int p) { 54 suf[pre[p]] = p; 55 pre[suf[p]] = p; 56 } 57 58 void remove(int p) { 59 suf[pre[p]] = suf[p]; 60 pre[suf[p]] = pre[p]; 61 } 62 63 int update(int p) { 64 int rt = inf; 65 if (pre[p]) 66 rt = ar[p] - ar[pre[p]]; 67 if (suf[p] <= n) 68 rt = min(rt, ar[suf[p]] - ar[p]); 69 return rt; 70 } 71 72 inline void solve() { 73 sort(cr + 1, cr + n + 1); 74 sort(qs + 1, qs + m + 1); 75 int c = 1; 76 for (int sid = 0; sid <= n / cs && c <= m; sid++) { 77 int mdzzr = min(cs * (sid + 1), n), ls = 0, lr = cs * sid, ce = mdzzr; 78 79 pre[0] = 0, ls = 0; 80 for (int i = 1; i <= n; i++) { 81 pre[cr[i].sc] = ls; 82 suf[ls] = cr[i].sc; 83 ls = cr[i].sc; 84 } 85 suf[n + 1] = n + 1, pre[n + 1] = ls, suf[ls] = n + 1; 86 87 for (int i = 1; i <= mdzzr; i++) 88 remove(i); 89 for (int i = n; i > mdzzr; i--) 90 remove(i); 91 L[mdzzr] = inf; 92 for (int i = mdzzr + 1; i <= n; i++) 93 add(i), L[i] = min(L[i - 1], update(i)); 94 for (int i = mdzzr; i > lr; i--) 95 add(i); 96 for (int i = n; i > mdzzr; i--) 97 remove(i); 98 99 for ( ; c <= m && qs[c].lid == sid; c++) { 100 int l = qs[c].l, r = qs[c].r; 101 if (qs[c].lid == qs[c].rid) { 102 for (int i = lr + 1; i < l; i++) 103 remove(i); 104 for (int i = mdzzr; i >= l; i--) 105 remove(i); 106 int res = inf; 107 for (int i = l; i <= r; i++) 108 add(i), res = min(res, update(i)); 109 for (int i = r + 1; i <= mdzzr; i++) 110 add(i); 111 for (int i = l - 1; i > lr; i--) 112 add(i); 113 qs[c].res = res; 114 } else { 115 while (mdzzr < r) 116 add(++mdzzr); 117 int res = inf; 118 for (int i = lr + 1; i <= ce; i++) 119 remove(i); 120 for (int i = ce; i >= l; i--) 121 add(i), res = min(res, update(i)); 122 for (int i = l - 1; i > lr; i--) 123 add(i); 124 qs[c].res = min(res, L[r]); 125 } 126 } 127 } 128 129 for (int i = 1; i <= m; i++) 130 while (qs[i].id != i) 131 swap(qs[i], qs[qs[i].id]); 132 for (int i = 1; i <= m; i++) 133 printf("%d\n", qs[i].res); 134 } 135 136 int main() { 137 init(); 138 solve(); 139 return 0; 140 }