51Nod - 1495-中國好區間-尺取法
阿新 • • 發佈:2018-11-11
題意:在某一序列中,問有多少個好區間------區間長度大於等於 K 並且第 K 大的數大於等於 T。
解題思路:
1、滿足第 K 大的數大於等於 T,相當於在該區間中至少有 K 個數大於等於 T------用字尾陣列儲存該序列中前 i 個位置大於 T 的數。
2、如果固定左端點,那麼對於一個好區間,那麼右端點一定是可以往後延續的,若左端點向右移動,那麼離它最近的右端點不可能向左移動。因此可以使用雙指標來做這題。
3、如果固定右端點,那麼對於一個好區間,肯定是某個左端點往左都滿足題意,雙指標就ok了!
AC程式碼:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<queue> #include<stack> #include<vector> using namespace std; const int maxn = 1e7+5; int s[maxn]; int main() { ios::sync_with_stdio(false); long long a,n,k,T,b,c,p; cin>>n>>k>>T>>a>>b>>c>>p; s[0] = 0; for(int i = 1; i <= n; i++) { a = (a * b + c) % p; s[i] = s[i-1]; if(a >= T) s[i]++;//字首和--從 1-i 區間中大於 T 的個數 } long long ans = 0,l = 1,r = 1; // while(true) // { // while(s[r] - s[l-1] < k) r++; // if(r > n) break; // ans += n - r + 1; // l++; // } while(l <= n) { // r = k + l - 1;//從 l 開始的區間直接跳到到長度為 k,l 在往前移動,不需要重置 r,否則會超時。 while(r <= n) { if(s[r] - s[l-1] >= k)//這段區間中大於 T 的數的個數至少為 K { ans += n - r + 1; // 滿足條件之後,再加上任意一個都是滿足的區間 break; } r++; } if(r > n) break;//當 r>n 時,後面的就一定沒有滿足條件的區間 l++; } printf("%lld\n",ans); return 0; }