目錄傳送門
無論多麼麻煩的**寫完過後都要耐著性子檢查。
首先有樸素 \(n^2\) 的 \(\mathtt\)。
感覺這個思路太神辣!對區間 \([1,n]\) 進行分治。考慮在詢問 \(i\)第一次覆蓋區間 \(\text\) 時計算這個詢問。為什麼這是正確的?其實也就是為什麼 \([l,r]\) 一定覆蓋這個詢問?容易想到如果 \([l,r]\) 未覆蓋詢問 \(i\),詢問 \(i\) 一定越過了某個端點,而且這個端點不是 \(1/n\),也就是說一定是之前二分的乙個 \(\text\),這和第一次覆蓋區間 \(\rm mid\) 的假設相悖,所以得證。
不過如果我們還用樸素 \(\mathtt\),一切都是白瞎。甚至成功公升高了複雜度。
發現樸素 \(\mathtt\) 複雜度那麼高是因為要保證選取的數大於等於 \(l\),小於等於 \(r\) 這兩個條件,如果我們把這兩個條件拆開做,再合併起來會怎樣呢?看上去十分不可做。
在之前的操作中,我們保證了乙個很好的性質:\(l_i\le \text,r_i>\text\)。那麼所有詢問都可以被 \(\rm mid\) 劃分成兩段,如果分別從 \(\text,\text+1\) 開始向兩邊 \(\mathtt\),我們就確定了乙個端點,單次 \(\mathtt\) 複雜度就是 \(\mathcal o(n)\) 的啦!具體而言,列舉在 \([l,\text]\) 之間有多少條被選的語錄,所以一次 \(\mathtt\) 實際是 \(\mathcal o(nl)\) 的,然後花費 \(\mathcal o(l)\) 將其拼在一起。
時間複雜度 \(\mathcal o(nl\log n)\)。
#include #define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
#define print(x,y) write(x),putchar(y)
int read()
void write(int x)
#include using namespace std;
const int maxn=1e5+5;
int n,l,a[maxn],m,f[55][maxn],g[55][maxn],ans[maxn];
struct node q[maxn],tl[maxn],tr[maxn];
void calcl(int l,int r)
}void calcr(int l,int r)
rep(i,1,totl) q[ql+i-1]=tl[i];
rep(i,1,totr) q[ql+totl+i-1]=tr[i];
dicon(l,mid,ql,ql+totl-1),dicon(mid+1,r,ql+totl,ql+totl+totr-1);
}int main()
BZOJ3636 教義問答手冊
有三個不是那麼暴力的複雜度 o nlogn l ql qlogn 離線 然而只有離線的那個是滋磁的 4.4 等我細細道來 題意 有乙個長度為n的序列 元素有正有負 再來乙個l q組詢問,每次問區間 l,r 中,選出若干個不相交的長度正好是l的區間,使得和最大 總共有n l 1個區間嘛.再來乙個長度n...
BZOJ3636 教義問答手冊
傳送門乙個整數序列,給定若干詢問,每個詢問形如 在 l i,r i 中選若干個長度為 l 的不相交的區間,使得其和最大。比較容易寫出 mathcal o n 2 的 dp 定義 f 表示區間 l,r 的最大答案,那麼就有轉移方程 f max f sum ra i 預處理 mathcal o n 2 ...
BZOJ 3636 教義問答手冊 (分治)
乙個整數數列,多次詢問某段區間 li ri li ri 內,選出若干個長度為l l且不相交的連續段使選出來的數和最大。首先想樸素的區間dpd p設f i j f i j 表示區間 i,j i j 的答案。o n 2 o n2 轉移比較顯然。f i j ma x f i j 1 f i j l k j...