Luogu3793 由乃救爺爺 分塊、ST表
阿新 • • 發佈:2019-02-06
瓶頸 cin 查詢 rac 快排 class new clu ons
,如果\(be_i \neq be_r\)查詢\(rmax_l , lmax_r\)以及\(be_l+1\)到\(be_r-1\)的所有塊的最大值,三者取\(max\);如果\(be_l = be_r\)就暴力
傳送門
因為昨天寫暴力寫掛在UOJ上用快排慘遭卡常,所以今天準備寫一個卡常題消遣消遣,然後時間又墊底了QAQ
這道題顯然需要支持一個\(O(N)\)預處理\(O(1)\)查詢的ST表,顯然普通的ST表是做不到的,因為預處理的時間太長了
於是分塊優化掉ST表的預處理
約定\(L_i,R_i\)表示第\(i\)個塊的左端點和右端點,\(be_i\)表示第\(i\)個數所在的塊
對於每一個位置\(i\)預處理\(L_{be_i}\)到\(i\)的所有數的最大值\(lmax_i\)以及\(i\)到\(R_{be_i}\)的所有數的最大值\(rmax_i\);預處理塊最大值的ST表
對於一個詢問\((l,r)\)
考慮復雜度,設塊長為\(S\),預處理復雜度瓶頸為ST表復雜度\(O(\frac{N}{S}log\frac{N}{S})\);詢問復雜度上,如果\(be_l \neq be_r\)為\(O(1)\),否則為\(O(S)\)。因為數據隨機,出現\(be_l = be_r\)的概率為\(\frac{S}{N}\),所以最壞查詢復雜度為\(O(S^2)\),總復雜度為\(O(\frac{N}{S}log\frac{N}{S} + S^2)\)
差不多當\(S = \sqrt[3]{NlogN}\)的時候有最優復雜度,但是因為數據隨機所以塊長開大一點也沒關系
然後可能需要一些奇怪的常數優化比如把max define掉之類的
#include<bits/stdc++.h> using namespace std; namespace GenHelper { unsigned z1,z2,z3,z4,b; 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); } } void srand(unsigned x) { using namespace GenHelper; z1=x; z2=(~x)^0x233333333U; z3=x^0x1234598766U; z4=(~x)+51; } int read() { using namespace GenHelper; int a=rand_()&32767; int b=rand_()&32767; return a*32768+b; } const int MAXN = 2e7 + 7; unsigned int arr[MAXN] , maxN1[MAXN] , maxN2[MAXN] , ST[15][26000] , logg2[26000]; unsigned int N , M , S , T , cnt; #define cmp(a , b) ((a) > (b) ? (a) : (b)) inline unsigned int qST(int x , int y){ if(x > y) return 0; int t = logg2[y - x + 1]; return cmp(ST[t][x] , ST[t][y - (1 << t) + 1]); } int main(){ cin >> N >> M >> S; srand(S); T = pow(N * log2(N) , 1.0/3); cnt = N / T + (N % T ? 1 : 0); for(int i = 1 ; i <= N ; ++i){ arr[i] = read(); maxN2[i] = arr[i]; if(i % T != 1) maxN2[i] = cmp(maxN2[i] , maxN2[i - 1]); } for(int i = N ; i ; --i){ maxN1[i] = arr[i]; if(i % T) maxN1[i] = cmp(maxN1[i] , maxN1[i + 1]); if(i % T == 1) ST[0][i / T + 1] = maxN1[i]; } for(int i = 2 ; i <= cnt ; ++i) logg2[i] = logg2[i >> 1] + 1; for(int i = 1 ; 1 << i <= cnt ; ++i) for(int j = 1 ; j + (1 << i) - 1 <= cnt ; ++j) ST[i][j] = cmp(ST[i - 1][j] , ST[i - 1][j + (1 << (i - 1))]); unsigned long long sum = 0; while(M--){ int l = read() % N + 1 , r = read() % N + 1; if(l > r) swap(l , r); if((l - 1) / T == (r - 1) / T){ unsigned int ans = 0; for(int i = l ; i <= r ; ++i) ans = cmp(ans , arr[i]); sum += ans; } else sum += cmp(cmp(maxN1[l] , maxN2[r]) , qST((l - 1) / T + 2 , (r - 1) / T)); } cout << sum; return 0; }
Luogu3793 由乃救爺爺 分塊、ST表