BZOJ 3489: A simple rmq problem(K-D Tree)
Submit:?2579??Solved:?888
[Submit][Status][Discuss]
Description
因為是OJ上的題,就簡單點好了。給出一個長度為n的序列,給出M個詢問:在[l,r]之間找到一個在這個區(qū)間里只出現(xiàn)過一次的數(shù),并且要求找的這個數(shù)盡可能大。如果找不到這樣的數(shù),則直接輸出0。我會采取一些措施強制在線。
?
?
Input
第一行為兩個整數(shù)N,M。M是詢問數(shù),N是序列的長度(N<=100000,M<=200000)
第二行為N個整數(shù),描述這個序列{ai},其中所有1<=ai<=N
再下面M行,每行兩個整數(shù)x,y,
詢問區(qū)間[l,r]由下列規(guī)則產(chǎn)生(OIER都知道是怎樣的吧>_<):
l=min((x+lastans)mod?n+1,(y+lastans)mod?n+1);
r=max((x+lastans)mod?n+1,(y+lastans)mod?n+1);
Lastans表示上一個詢問的答案,一開始lastans為0
?
Output
一共M行,每行給出每個詢問的答案。
?
Sample Input
10 106 4 9 10 9 10 9 4 10 4
3 8
10 1
3 4
9 4
8 1
7 8
2 9
1 1
7 3
9 9
Sample Output
410
10
0
0
10
0
4
0
4
HINT
?
注意出題人為了方便,input的第二行最后多了個空格。
2015.6.24新加數(shù)據(jù)一組,2016.7.9放至40S,600M,但未重測
?
?
Source
by zhzqkkk
網(wǎng)上又沒有代碼,自己yy了一上午才寫出來 對于這道題目,我們記$pre_i$表示$i$號位置的元素前一次出現(xiàn)的位置 記$nxt_i$表示$i$號位置的元素后一次出現(xiàn)的位置 假設詢問區(qū)間為$l,r$ 那么$i$號位置滿足條件,當且僅當$l<=i<=r, pre_i < l, nxt_i > r$ 這樣我們把$i, pre_i, nxt_i$看成一個三元組 然后用K-D tree加剪紙就行了 剪紙的時候考慮三種情況- 詢問區(qū)間完全包含該節(jié)點及其左右兒子,直接通過打標記統(tǒng)計出最大值
- 詢問區(qū)間包含該節(jié)點但不包含其左右兒子,直接統(tǒng)計該節(jié)點對答案的貢獻
- 詢問區(qū)間與該節(jié)點及其左右兒子不重合,直接return
有了這三種剪枝,而且此題沒有插入,因此復雜度為$O(mn\sqrt{n})$
?
#include<cstdio> #include<cstring> #include<algorithm> #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2)? EOF : *p1++) using namespace std; const int MAXN = 1e6 + 10; char buf[1 << 21], *p1 = buf, *p2 = buf; inline int read() {char c = getchar(); int x = 0, f = 1;while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();return x * f; } int N, M, root, WD; int Ql, Qr, lastans = 0; struct Point {int x[4];bool operator < (const Point &rhs) const{return x[WD] < rhs.x[WD];} }P[MAXN]; #define ls(x) T[x].ls #define rs(x) T[x].rs struct KDTree {int ls, rs, mn[3], mx[3], val;Point tp; }T[MAXN]; int a[MAXN], pre[MAXN], nxt[MAXN], happen[MAXN]; void update(int k) {for(int i = 0; i <= 2; i++) {T[k].mn[i] = T[k].mx[i] = T[k].tp.x[i];if(ls(k)) T[k].mn[i] = min(T[ls(k)].mn[i], T[k].mn[i]), T[k].mx[i] = max(T[ls(k)].mx[i], T[k].mx[i]);if(rs(k)) T[k].mn[i] = min(T[rs(k)].mn[i], T[k].mn[i]), T[k].mx[i] = max(T[rs(k)].mx[i], T[k].mx[i]);}T[k].val = max(T[k].tp.x[3], T[ls(k)].val);T[k].val = max(T[k].val, T[rs(k)].val); } int Build(int l, int r, int wd) {if(l > r) return 0;int mid = l + r >> 1; WD = wd;nth_element(P + l, P + mid, P + r + 1);T[mid].tp = P[mid];ls(mid) = Build(l, mid - 1, (wd + 1) % 3);rs(mid) = Build(mid + 1, r, (wd + 1) % 3);update(mid);return mid; } bool CheckInclude(int k) {if(T[k].mn[0] >= Ql && T[k].mx[0] <= Qr&& T[k].mx[1] < Ql && T[k].mn[2] > Qr) return 1;return 0; } bool CheckCross(int k) {if(T[k].tp.x[0] >= Ql && T[k].tp.x[0] <= Qr&& T[k].tp.x[1] < Ql && T[k].tp.x[2] > Qr) return 1;return 0; } bool CheckNotCross(int k) {if(T[k].mn[1] >= Ql || T[k].mx[2] <= Qr || T[k].mx[0] < Ql || T[k].mn[0] > Qr) return 1;return 0; } void Query(int k) {if(CheckInclude(k)) {lastans = max(lastans, T[k].val); return ; //矩形完全包含在查詢區(qū)間內(nèi) }if(CheckCross(k)) lastans = max(lastans, T[k].tp.x[3]); //相交 if(CheckNotCross(k)) return ; // 沒有重合的地方 int disl = T[ls(k)].val, disr = T[rs(k)].val;if(disl > disr) {if(disl > lastans) Query(ls(k));if(disr > lastans) Query(rs(k));}else {if(disr > lastans) Query(rs(k));if(disl > lastans) Query(ls(k));} } int main() {#ifdef WIN32freopen("a.in", "r", stdin);freopen("a.out", "w", stdout);#endifN = read(); M = read();for(int i = 1; i <= N; i++) a[i] = read();for(int i = 1; i <= N; i++) pre[i] = happen[a[i]], happen[a[i]] = i;for(int i = 1; i <= N; i++) happen[a[i]] = N + 1;for(int i = N; i >= 1; i--) nxt[i] = happen[a[i]], happen[a[i]] = i;for(int i = 1; i <= N; i++)P[i] = (Point) {i, pre[i], nxt[i], a[i]};root = Build(1, N, 0);for(int i = 1; i <= M; i++) {int x = read(), y = read(); Ql = min((x + lastans) % N + 1,(y + lastans) % N + 1);Qr = max((x + lastans) % N + 1,(y + lastans) % N + 1);lastans = 0;Query(root);printf("%d\n", lastans);}return 0; }?
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的BZOJ 3489: A simple rmq problem(K-D Tree)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle APEX 系列文章7:Or
- 下一篇: Yii2.0实现微信公众号后台开发