日常訓練 seq 數列分割

2021-08-18 08:30:21 字數 2185 閱讀 1767

轉移就變為 g[

i]=(

∑j=1

i−1g

[j],

s[j]

≥s[i

]−mi

d)<<

1 g[i

]=(∑

j=1i

−1g[

j],s

[j]≥

s[i]

−mid

)<<

1。把

s[i]s[

i]

按從大到小排序,可知此時合法的

j j

是乙個字首。

因此把 s[

i]' role="presentation" style="position: relative;">s[i

]s[i

]離散化,作為樹狀陣列的下標維護字首和來轉移。

此時 d

p d

p複雜度 o(

nklogn

) o(n

klog⁡n

),仍然不能通過。

進一步地,我們會發現:g[i]g

[i

]中為 tru

e tru

e的部分一定是一段連續的區間,只需要用區間的左右邊界來表示。

容易證明,一開始 g[

0]= g[0

]=

滿足條件,之後的轉移只涉及上述兩種運算,因此也滿足條件。

此時就可設 g[

i]= g[i

]=

,初始時 g[

0]= g[0

]=

,則:

因此計算 g[i]g

[i

]的部分就被優化掉了,dpdp

的時間複雜度 o(

nlogn)o(

nlog⁡n

)。

#include 

#include

#include

#include

#include

using

namespace

std;

namespace inout

inline

int get()

};using

namespace inout;

const

int m = 15005;

const

int maxn = 0x3f3f3f3f;

int n, k, m, l = maxn, r = -maxn, ans;

int f[m], g[m], sum[m], to[m], b[m];

inline

int max(int x, int y)

inline

int min(int x, int y)

inline

void ckmin(int &x, int y)

inline

void ckmax(int &x, int y)

struct line

line(int l, int r):

l(l), r(r) {}

inline

void

operator += (const line &x)

}c[m], h[m];

const line inf = line(maxn, -maxn);

inline line right(const line &x)

inline

void modify(int x, const line &y)

inline line query(int x)

inline

bool check(int mid)

return h[n - 1].r == k;

}int main()

sort(b + 1, b + n + 2);

m = unique(b + 1, b + n + 2) - b - 1;

for (int i = 0; i <= n; ++i)

to[i] = lower_bound(b + 1, b + m + 1, -sum[i]) - b;

++n;

while (l <= r)

printf("%d\n", ans);

return

0;}

日常訓練 分割田地

地主某君有一塊由2 n個柵格組成的土地,有k個兒子,現在地主快要終老了,要把這些土地分給這些兒子。分給每個兒子的土地最小的單位是乙個柵格,同時,分給同乙個兒子的土地要求要相鄰連續的。地主覺得分給某個兒子的土地面積至少有乙個柵格,但是具體多少可以隨意。請問,聰明的你,能夠算出地主一共有多少種分土地的方...

CDOJ 1157 數列 seq 分塊

題意 給出乙個數列,兩種操作 1.修改操作 把數列中第i個數改為x 2.詢問操作 給定乙個位置i,問數列中有多少個位置j j i 滿足位置i與位置j間所有的數都不超過ai與aj的較大值。簡單來說,操作2分為兩部分 1.位置i右邊相鄰連續的比它小的數字個數 2.位置i右邊不減序列長度 直接將數列分塊,...

Seq(規律 等差數列)

剛開始我還沒什麼頭緒,估計一看就是規律吧,結果打了一下表 然後發現這樣寫 然後很明顯的等差數列就出來了,最後通式一帶判斷一下餘數和計算行數就ac了 include include include include include include include include include incl...