BZOJ 3489: A simple rmq problem
3489: A simple rmq problem
Time Limit:?40 Sec??Memory Limit:?600 MBSubmit:?1594??Solved:?520
[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 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新加數據一組,2016.7.9放至40S,600M,但未重測
?
?
Source
by zhzqkkk
[Submit][Status][Discuss]?
參考了網上的一些做法,可持久化樹套樹什么的實在吃不消,于是采用了KD-Tree的方法。
考慮一個點,在哪個區間內它是唯一出現的呢?
設prev[i]為上一個和i處權值相同的位置,next[i]為下一個和i處權值相同的位置,顯然在(prev[i],next[i])這個區間內,i點是該權值唯一出現的位置。
對于一個詢問(ql,qr),我們可以轉換為:找出滿足 prev[i] < ql 且 next[i] > qr 且 ql <= i <= qr 的i中,權值最大的i。這個就是KD-Tree維護三維的區間最值問題。
?
1 #include <bits/stdc++.h> 2 3 inline int getC(void) { 4 static const int siz = 1024; 5 6 static char buf[siz]; 7 static char *hd = buf + siz; 8 static char *tl = buf + siz; 9 10 if (hd == tl) 11 fread(hd = buf, 1, siz, stdin); 12 13 return int(*hd++); 14 } 15 16 inline int getI(void) { 17 register int ret = 0; 18 register int neg = false; 19 register int bit = getC(); 20 21 for (; bit < 48; bit = getC()) 22 if (bit == '-')neg ^= true; 23 24 for (; bit > 47; bit = getC()) 25 ret = ret * 10 + bit - '0'; 26 27 return neg ? -ret : ret; 28 } 29 30 template <class T> 31 inline T min(const T &a, const T &b) { 32 return a < b ? a : b; 33 } 34 35 template <class T> 36 inline T max(const T &a, const T &b) { 37 return a > b ? a : b; 38 } 39 40 const int maxn = 100005; 41 42 int n, m; 43 int answer; 44 int num[maxn]; 45 46 int next[maxn]; 47 int prev[maxn]; 48 int last[maxn]; 49 50 int value[maxn][3]; 51 52 int pos[maxn]; 53 int maxv[maxn]; 54 int lson[maxn]; 55 int rson[maxn]; 56 int mini[maxn][3]; 57 int maxi[maxn][3]; 58 59 int qryL, qryR; 60 61 int cmpK; 62 63 inline bool cmp(const int &a, const int &b) { 64 return value[a][cmpK] < value[b][cmpK]; 65 } 66 67 int build(int l, int r, int k) { 68 int mid = (l + r) >> 1; cmpK = k; 69 std::nth_element( 70 pos + l, pos + mid, pos + r + 1, cmp); 71 maxv[mid] = num[pos[mid]]; 72 for (int i = 0; i < 3; ++i) 73 mini[mid][i] = maxi[mid][i] = value[pos[mid]][i]; 74 if (l < mid) { 75 lson[mid] = build(l, mid - 1, (k + 1) % 3); 76 maxv[mid] = max(maxv[mid], maxv[lson[mid]]); 77 for (int i = 0; i < 3; ++i) { 78 mini[mid][i] = min(mini[mid][i], mini[lson[mid]][i]); 79 maxi[mid][i] = max(maxi[mid][i], maxi[lson[mid]][i]); 80 } 81 } 82 if (r > mid) { 83 rson[mid] = build(mid + 1, r, (k + 1) % 3); 84 maxv[mid] = max(maxv[mid], maxv[rson[mid]]); 85 for (int i = 0; i < 3; ++i) { 86 mini[mid][i] = min(mini[mid][i], mini[rson[mid]][i]); 87 maxi[mid][i] = max(maxi[mid][i], maxi[rson[mid]][i]); 88 } 89 } 90 return mid; 91 } 92 93 inline bool check(int t) { 94 if (mini[t][0] > qryR || maxi[t][0] < qryL)return false; 95 if (mini[t][1] >= qryL || maxi[t][2] <= qryR)return false; 96 return true; 97 } 98 99 void query(int t) { 100 if (mini[t][0] >= qryL && maxi[t][0] <= qryR && maxi[t][1] < qryL && mini[t][2] > qryR) 101 { answer = max(answer, maxv[t]); return; } 102 if (pos[t] >= qryL && pos[t] <= qryR && prev[pos[t]] < qryL && next[pos[t]] > qryR) 103 answer = max(answer, num[pos[t]]); 104 if (maxv[lson[t]] > maxv[rson[t]]) { 105 if (lson[t] && maxv[lson[t]] > answer && check(lson[t]))query(lson[t]); 106 if (rson[t] && maxv[rson[t]] > answer && check(rson[t]))query(rson[t]); 107 } 108 else { 109 if (rson[t] && maxv[rson[t]] > answer && check(rson[t]))query(rson[t]); 110 if (lson[t] && maxv[lson[t]] > answer && check(lson[t]))query(lson[t]); 111 } 112 } 113 114 signed main(void) { 115 n = getI(); 116 m = getI(); 117 118 for (int i = 1; i <= n; ++i) 119 num[i] = getI(); 120 121 for (int i = 1; i <= n; ++i) 122 last[i] = 0; 123 124 for (int i = 1; i <= n; ++i) 125 prev[i] = last[num[i]], last[num[i]] = i; 126 127 for (int i = n; i >= 1; --i) 128 last[i] = n + 1; 129 130 for (int i = n; i >= 1; --i) 131 next[i] = last[num[i]], last[num[i]] = i; 132 133 for (int i = 1; i <= n; ++i) { 134 pos[i] = i; 135 value[i][0] = i; 136 value[i][1] = prev[i]; 137 value[i][2] = next[i]; 138 } 139 140 int root = build(1, n, 0); 141 142 for (int i = 1; i <= m; ++i) { 143 int x = getI(); 144 int y = getI(); 145 qryL = (x + answer) % n + 1; 146 qryR = (y + answer) % n + 1; 147 if (qryL > qryR) 148 qryL ^= (qryR ^= (qryL ^= qryR)); 149 answer = 0; query(root); printf("%d\n", answer); 150 } 151 }?
@Author: YouSiki
?
轉載于:https://www.cnblogs.com/yousiki/p/6242135.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的BZOJ 3489: A simple rmq problem的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从菜鸟成为数据科学家的养成方案
- 下一篇: 前端构建工具学习