11.17 鮮花(RMQ專題)
哈哈,回家看到樸彩英這個歌繃不住了。
不是吧,姐?
推歌-박채영《아파트》
채영이가 좋아하는
랜덤 게임
랜덤 게임
Game start
아파트 아파트
아파트 아파트
아파트 아파트
Uh, uh huh uh huh
아파트 아파트
아파트 아파트
아파트 아파트
Uh, uh huh uh huh
Kissy face, kissy face
Sent to your phone but,
I'm trying to kiss your lips for real
Red hearts, red hearts
That’s what I’m on yeah
Come give me something I can feel
Oh oh oh
Don't you want me like I want you, baby
Don't you need me like I need you now
Sleep tomorrow but tonight go crazy
All you gotta do is just meet me at the
아파트 아파트
아파트 아파트
아파트 아파트
Uh, uh huh uh huh
아파트 아파트
아파트 아파트
아파트 아파트
Uh, uh huh uh huh
It’s whatever it’s whatever it’s whatever you like
Turn this 아파트 into a club
I’m talking drink, dance, smoke, freak, party all night
건배 건배 girl what’s up
Oh oh oh
Don't you want me like I want you, baby
Don't you need me like I need you now
Sleep tomorrow but tonight go crazy
All you gotta do is just meet me at the
아파트 아파트
아파트 아파트
아파트 아파트
Uh, uh huh uh huh
아파트 아파트
아파트 아파트
아파트 아파트
Uh, uh huh uh huh
Hey so now you know the game
Are you ready?
Cause I’m comin to get ya
Get ya, get ya
Hold on, hold on
I’m on my way
Yeah yeah yeah yeah yeah
I’m on my way
Hold on, hold on
I’m on my way
Yeah yeah yeah yeah yeah
I’m on my way
Don't you want me like I want you, baby
Don't you need me like I need you now
Sleep tomorrow but tonight go crazy All
you gotta do is just meet me at the
아파트 아파트
아파트 아파트
아파트 아파트
Just meet me at the
(Uh huh uh huh)
아파트 아파트
아파트 아파트
아파트 아파트
Just meet me at the
(Uh huh uh huh)
아파트 아파트
아파트 아파트
아파트 아파트
Just meet me at the
(Uh huh uh huh)
아파트 아파트
아파트 아파트
아파트 아파트
Uh, uh huh uh huh
省流: \(HANGRY\_Sol\) 牌拍子大大地好用!
RMQ 專題
四毛子(Four Russian)演算法
據說是四個俄羅斯科學家發明的。
還是舉區間最大值的例子。
我們把這麼個區間分塊,分成左邊散塊,中間整塊,右邊散塊。
然後如果我們把塊長調成 \(\frac{\log_2n}{2}\) 然後發現這個可以 \(\mathcal{O}(n)\) 預處理( \(\mathcal{O}(\frac{n}{len}\log{\frac{n}{len}})\) ), \(\mathcal{O}(1)\) 查詢。
但是這個區間在一個塊裡面怎麼辦?
然後這四隻毛熊就開始唐了。
首先噢,先建一顆大根笛卡爾樹。
然後統計一下 \(dfs\) 序。發現 \(LCA\) 就是最大值。
轉化成 \(dfs\) 序,即 \(\pm RMQ\) 問題。
對於長度為 \(len = \frac{\log_2n}{2}\) 的塊來說,他只有 \(\mathcal{O}(\sqrt N)\) 種不同的情況吧。
我們直接對於每個塊的情況狀壓,最後統計一下第 \(i\) 種, \([l, r]\) 的最大值。
時間複雜度 \(\mathcal{O}(n)\) , 空間複雜度 \(\mathcal{O}(N)\) 。
然後你就發現不僅難寫,常數還賊大。
伯約的這真有單 log 跑得快嗎?
然後考慮怎麼最佳化一下這個東西。
我們發現這個題的瓶頸就在於兩個端點在一個塊時的情況。
然後發現塊長為 \(\log\) 級,也就是說 \(r - l \le \log n\)
那我們直接跑殘疾 \(ST\) 表,跑到 \(\log\log n\) 大概 \(2 \times 10 ^ 7\) 才 \(4\) 的樣子。
額……這是不是能叫…… \(O(n)\) ?
有興趣的可以去由乃救爺爺草草,應該可以過的。
四毛子 Pro Max : 二毛子
感覺這個東西就應該叫四毛娘吧,畢竟閹割了……
這個和四毛子後面我想的的那個東西異曲同工,都是在對於兩個端點在同一個塊時的最佳化。
考慮一個顯然的性質,對於一個區間 \([l, r]\) , 其區間最值的位置肯定是
其實為什麼考慮這個呢,就是因為開不下,想想有沒有什麼能夠最佳化空間的。
這個 \(maxpos\) 顯然可單調棧維護。發現這個後,直接將 \(maxpos_{i, r}\) 在 \(r\) 處狀壓。查的時候先將 \(l\) 前的清掉,然後再找第一個 \(1\)(函式 builtin_ctzll(ull)
可以完成這個操作,複雜度為 \(\log\log\) 或常數)。
然後就做完了。這個寫了,可以給碼。
CODE of 由乃救爺爺
#include <bits/stdc++.h>
#define int unsigned int
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int N = 2e7 + 100;
int a[N], n, m; ull s;
int st[21], top;
namespace GenHelper {
unsigned z1, z2, z3, z4, b;
inline unsigned rand_() {
b = ((z1 << 6) ^ z1) >> 13;
z1 = ((z1 & 4294967294U) << 18) ^ b;
b = ((z2 << 2) ^ z2) >> 27;
z2 = ((z2 & 4294967288U) << 2) ^ b;
b = ((z3 << 13) ^ z3) >> 21;
z3 = ((z3 & 4294967280U) << 7) ^ b;
b = ((z4 << 3) ^ z4) >> 12;
z4 = ((z4 & 4294967168U) << 13) ^ b;
return (z1 ^ z2 ^ z3 ^ z4);
}
}
inline void srand(unsigned x) {
using namespace GenHelper;
z1 = x; z2 = (~ x) ^ 0x233333333U; z3 = x ^ 0x1234598766U; z4 = (~ x) + 51;
}
inline int read() {
using namespace GenHelper;
int a = rand_() & 32767;
int b = rand_() & 32767;
return a * 32768 + b;
}
#define l(x) ((x - 1) << 6 | 1)
#define r(x) (x << 6)
#define belong(x) ((x + 63) >> 6)
int ST[__lg(N >> 6) + 1][N >> 6];
ull val[N]; int lg[N];
int Prefix[N], Suffix[N];
inline int MaxST(int l, int r) {
if (l > r) return 0;
int k = lg[r - l + 1];
return max(ST[k][l], ST[k][r - (1 << k) + 1]);
}
inline void In() {
int tot = belong(n), Maxer;
for (int i = 2; i <= n; ++ i) lg[i] = lg[i >> 1] + 1;
for (int i = 1; i <= tot; ++ i) {
Maxer = 0;
for (int j = l(i); j <= r(i); ++ j) Maxer = max(Maxer, a[j]), Prefix[j] = Maxer;
Suffix[r(i)] = a[r(i)];
for (int j = r(i) - 1; j >= l(i); -- j) Suffix[j] = max(Suffix[j + 1], a[j]);
ST[0][i] = Maxer;
}
for (int j = 1; j <= __lg(belong(n)); ++ j)
for (int i = 1; i <= tot - (1 << j) + 1; ++ i)
ST[j][i] = max(ST[j - 1][i], ST[j - 1][i + (1 << (j - 1))]);
for (int j = 1; j <= tot; ++ j) {
top = 0;
for (int i = l(j); i <= r(j); ++ i) {
if (i > l(j)) val[i] = val[i - 1];
while (top && a[st[top]] <= a[i]) {
val[i] ^= (1ULL << (st[top] - l(j))); -- top;
}
val[i] |= (1ULL << (i - l(j)));
st[++ top] = i;
}
}
}
inline int Query(int x, int y) {
if (belong(x) == belong(y)) return a[x + __builtin_ctzll(val[y] >> (x - l(belong(x))))];
return max(max(Prefix[y], Suffix[x]), MaxST(belong(x) + 1, belong(y) - 1));
}
signed main() {
cin >> n >> m >> s;
srand(s); int l, r; ull ans = 0;
for (int i = 1; i <= n; ++ i) a[i] = read();
In();
while (m --) {
l = read() % n + 1, r = read() % n + 1;
if (l > r) swap(l, r);
ans += Query(l, r);
}
cout << ans;
}