DarkBZOJ3636 教義問答手冊

2022-06-19 17:15:11 字數 1724 閱讀 4024

如何評價題解看不懂只能自己把這道題想出來。

明明就是懶得看題解啊喂!(#`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 詢問...