日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 3489: A simple rmq problem(K-D Tree)

發布時間:2025/4/5 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 3489: A simple rmq problem(K-D Tree) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Time Limit:?40 Sec??Memory Limit:?512 MB
Submit:?2579??Solved:?888
[Submit][Status][Discuss]

Description

因為是OJ上的題,就簡單點好了。給出一個長度為n的序列,給出M個詢問:在[l,r]之間找到一個在這個區間里只出現過一次的數,并且要求找的這個數盡可能大。如果找不到這樣的數,則直接輸出0。我會采取一些措施強制在線。

?

?

Input

第一行為兩個整數N,M。M是詢問數,N是序列的長度(N<=100000,M<=200000)

第二行為N個整數,描述這個序列{ai},其中所有1<=ai<=N

再下面M行,每行兩個整數x,y,

詢問區間[l,r]由下列規則產生(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 10
6 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

4
10
10
0
0
10
0
4
0
4

HINT

?



注意出題人為了方便,input的第二行最后多了個空格。


2015.6.24新加數據一組,2016.7.9放至40S,600M,但未重測


?

?

Source

by zhzqkkk

網上又沒有代碼,自己yy了一上午才寫出來 對于這道題目,我們記$pre_i$表示$i$號位置的元素前一次出現的位置 記$nxt_i$表示$i$號位置的元素后一次出現的位置 假設詢問區間為$l,r$ 那么$i$號位置滿足條件,當且僅當$l<=i<=r, pre_i < l, nxt_i > r$ 這樣我們把$i, pre_i, nxt_i$看成一個三元組 然后用K-D tree加剪紙就行了 剪紙的時候考慮三種情況
  • 詢問區間完全包含該節點及其左右兒子,直接通過打標記統計出最大值
  • 詢問區間包含該節點但不包含其左右兒子,直接統計該節點對答案的貢獻
  • 詢問區間與該節點及其左右兒子不重合,直接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 ; //矩形完全包含在查詢區間內 }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; }

?

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的BZOJ 3489: A simple rmq problem(K-D Tree)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。