poj 3061 二分 or 尺取法

2022-05-02 22:12:10 字數 2074 閱讀 1014

傳送門:problem 3061

馬上就要去上課了,先獻上二分ac**,其餘的有空再補

題意:

給定長度為 n 的整數數列 a[0,1,2,........,n]以及整數 s。

求出總和不小於 s 的連續子串行的長度的最小值。

如果解不存在,則輸出 0。

題解:

1、二分

由於所有的元素都大於 0 ,所以陣列a[ ] 的字首和sum[ ]為遞增的序列,滿足二分的條件。

首先確定子串行的起點為start(start的可能取值為 1,2,......,n)。

假設區間[start,end]是以start為子串行起點的最小區間,則需要滿足 sum[end]-sum[start-1] >= s,而確定滿足條件的最小的 end 用二分即可在o(longn)的時間完成。

所以總的時間複雜度為 o(nlogn)

2、尺取法

設以a[start]為子串行起點的總和最初大於s的連續子串行為a[start,......,end],此時 res = end-start+1;

(1):end++,找到最大的 k ,使得在去除當前子串行的前 k 個數後依舊滿足 sum[end]-sum[start-1 + k] >= s,並判斷是否需要更新 res。

(2):重複(2)過程,直到 end > n 為止。

ac**:

1 #include2 #include3 #include4

using

namespace

std;

5#define mem(a,b) (memset(a,b,sizeof(a)))

6const

int maxn=1e5+50;7

8int

n,s;

9int

a[maxn];

10int

sum[maxn];

11int binarysearch(int

val)

1222

return

r;23}24

intmain()

2538

for(int s=1;s <= n;++s)

3944 printf("

%d\n

",res);45}

46 }

二分

1 #include2 #include3 #include4

using

namespace

std;

5#define pb push

6const

int maxn=1e5+50;7

8int

n,s;

9int

a[maxn];

10 queuemyqueue;

1112

intmain()

1332

if(sum >=s)

3340

while(end <=n)

4149 res= res > myqueue.size() ? myqueue.size():res;//

判斷是否更新 res50}

51}52else

53 res=0

;54 printf("

%d\n

",res);55}

56 }

view code

1 #include2 #include3 #include4

using

namespace

std;

5const

int maxn=1e5+50;6

7int

n,s;

8int

a[maxn];910

intsolve()

1124

return

res;25}

2627

intmain()

2838 }

尺取法&挑戰程式設計競賽

POJ 3061 二分 字首和or尺取法

題目鏈結 題目大意 找到最短的序列長度,使得序列元素和大於s。解題思路 兩種思路。一種是二分 字首和。複雜度o nlogn 有點慢。二分列舉序列長度,如果可行,向左找小的,否則向右找大的。字首和預處理之後,可以o 1 內求和。include cstdio include cstring int su...

Subsequence 尺取法 二分)

傳送門 法1 字首和 二分思想。預處理字首和以便於求區間和,然後列舉所有區間左端,二分查詢右端,用stl stlst l自帶的low er b ound lower bound lower boun d即可。時間複雜度 o n logn o nlogn o nlog n 法2 尺取法,列舉區間左端點...

51nod 1686 二分 尺取法

題意 給出陣列,區間的值為其重數 這個重數是指區間內的重數,不是整個陣列的重數 求解第k大小的區間值 重數 題解 思路 二分 尺取法 由上知 重數的範圍為 1 100000 重數值大的區間一定包括重數值小的區間 因此找到有大於等於k個區間值為mid就是答案了 注意 有可能第k大的值和第k 1個 或者...