傳送門: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 #include4view codeusing
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 }
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個 或者...