如何評價題解看不懂只能自己把這道題想出來。
明明就是懶得看題解啊喂!(#`o′)
個人感覺這個應該不算 \(\tt cdq\)分治,但是又不知道怎麼分類,於是。。。
darkbzoj
分治其實就是按一定順序做就可以保證時間複雜度的暴力。
所以我們先考慮 \(o(n^2)\) 的 \(\tt dp\),顯然我們可以令 \(dp_\) 表示區間 \([l,r]\) 的最大劃分。
考慮優化。
我們注意到 \(l\le 50\),這給了我們亂搞的資本。
考慮將詢問丟到各個區間裡面分治,如果乙個詢問完全被乙個大區間 \([l,r]\) 的子區間包含,給這個子區間就好。這裡我們認為 \([l,r]\) 的子區間為 \([l,mid]\) 和 \([mid+1,r]\) ,和線段樹是一樣的。
如果這個詢問跨越了中間的邊界 \(mid\) 怎麼辦?由於 \(l\) 很小,我們可以列舉它在左邊的長度,當然在右邊的長度也可以計算出來。中間越界的部分是乙個長度為 \(l\) 的區間加,兩邊是可以預處理的乙個 \(\tt dp\)。
思路不難,細節有點多。
//12252024832524
#include #include #include #define tt templateusing namespace std;
typedef long long ll;
const int maxn = 100005;
const int maxl = 52;
int n,len,q;
int a[maxn],ans[maxn];
ll read()
while(c >= '0' && c <= '9')
return x * f;
}tt void put1(t x)
tt void put(t x,char c = -1)
tt t max(t x,t y)
tt t min(t x,t y)
tt t abs(t x)
struct query
q[maxn],lq[maxn],rq[maxn];
int dpl[maxl][maxn],dpr[maxl][maxn];//這裡的l,r指的是左邊的區間和右邊的區間
//右邊界空出i,j開始dp [j,mid-i];左邊界空出i,j開始dp [mid+1+i,j]
void workl(int l,int r)
}} void workr(int l,int r) }}
void solve(int l,int r,int ql,int qr)
int mid = (l+r) >> 1,ln = 0,rn = 0;
workl(l,mid); workr(mid+1,r);
for(int i = ql;i <= qr;++ i) }
for(int i = 1;i <= ln;++ i) q[ql+i-1] = lq[i];
for(int i = 1;i <= rn;++ i) q[ql+ln+i-1] = rq[i];
solve(l,mid,ql,ql+ln-1); solve(mid+1,r,ql+ln,ql+ln+rn-1);
}int main()
solve(1,n,1,q);
for(int i = 1;i <= q;++ i) put(ans[i],'\n');
return 0;
}
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 教義問答手冊
目錄傳送門 無論多麼麻煩的 寫完過後都要耐著性子檢查。首先有樸素 n 2 的 mathtt 感覺這個思路太神辣!對區間 1,n 進行分治。考慮在詢問 i 第一次覆蓋區間 text 時計算這個詢問。為什麼這是正確的?其實也就是為什麼 l,r 一定覆蓋這個詢問?容易想到如果 l,r 未覆蓋詢問 i 詢問...