返回的推進區間開頭和結尾,求滿足條件的最小區間的方法稱為尺取法。尺取法,顧名思義,像尺子一樣,一塊一塊的擷取。用尺取法來優化,使複雜度降為了o(n)。
整個過程分為四步:
1.初始化左右端點
2.不斷擴大右端點,直到滿足條件
3.如果第二步中無法滿足條件,則終止,否則更新結果
4.將左端點擴大1,然後回到第二步
例題:poj 3061
poj 2566
下面貼**(本人蒟蒻勿噴qwq
<
span style="color:#000000;">// poj 3061
#include#includeusing namespace std;
const int maxn=100010;
int num[maxn];
int n,s;
int main()
int sum = 0,s = 1,e = 1;
int ans = n + 1;
for(;;)
if(sum < s)
ans = min(ans ,e - s);
sum -= num[s++];
} if(ans == n + 1)
cout<<0<
//poj 2566
#include #include #include using namespace std;
const int maxn = 100000 + 5;
const int inf = 0x3f3f3f3f;
int a[maxn],n,k;
struct sum
} s[maxn];
inline void qry(int x)
if(t > x) ++ l;
else if(t < x) ++ r;
else break;
if(l == r) ++ r;
}if(rc_l > rc_r) swap(rc_l,rc_r);
printf("%d %d %d\n",rc,rc_l + 1,rc_r);
}int main()
}return 0;
}
首先
第一題保證每個數不是負數,很簡單的用尺取法秒過,但要注意無解輸出0的情況。
其次第二題,不能保證每個數是否大於0,不能滿足單調;
但是,我們要求的是數列和的絕對值,就可以做點什麼事了。
絕對值滿足性質:| sum[i] - sum[j] | == | sum[j] - sum[i] |
因此,我們就能改變字首和的順序了;
然後,就可以按照3061的尺取法思路求解了。
嗯嗯,就是這樣。
尺取法大致就是這樣,(霧
尺取法學習筆記
今天老師講了提了下尺取,於是就有了這篇筆記 ps 我覺得我們老師形容得很貼切,尺取就像蟲子蠕動一樣給出乙個序列,求區間和大於或者等於s的最短區間長度.3 2 8 10 5 3 8 4 2 9i 1 2 3 4 5 6 7 8 9 10 ai 3 2 8 10 5 3 8 4 2 9 l r 計算區間...
尺取法學習
參考資料 挑戰程式設計競賽 p146 參考部落格 介紹 尺取法 顧名思義,像尺子一樣取一段,借用挑戰書上面的話說,尺取法通常是對陣列儲存一對下標,即所選取的區間的左右端點,然後根據實際情況不斷地推進區間左右端點以得出答案。之所以需要掌握這個技巧,是因為尺取法比直接暴力列舉區間效率高很多,尤其是資料量...
ACM 學習記錄 尺取法
給定乙個陣列和乙個數s,在這個陣列中找乙個區間,使得這個區間之和等於s。例如 給定的陣列int x 14 和乙個s 15。那麼,可以找到的區間就應該有0到4,3到5,6到7.注意這裡的下標從0開始 對於這樣的題,不用任何技巧就可以跑出結果,例如下面這個方法可能是大多數人能夠想出來的 先用乙個陣列su...