51 nod 1495 中国好区间 奇葩卡时间题 700ms 卡O(n*log(n)), 思路:O(n)尺取法

来源:互联网 发布:阿里巴巴阿里云事业部 编辑:程序博客网 时间:2024/05/16 13:54
题目:

 

这个题目竟然叫中国好区间,要不要脸。欸,不得不说还蛮顺口的,哈哈哈。

 

首先我们有一个数组a。可以递推得来,O(n)时间复杂度。

 

定义left(有效区间的左端点),bigger(有效区间中大于等于T的数的数量)。

有效区间:a[left]~a[i],好区间:保持区间中有k个 >= T 的值。

好区间的数量:ans。

 

思路:

如果现在到了第i个值a[i]。

可能有以下四种情况。

1.bigger >= k && a[i] >= T

      bigger++,将left右移至有效区间中只有k个>=T的数,且a[left] >= T 。ans += left。(因为a[j]~a[i]( 1 <= j <= left)共left个全是好区间)

2.bigger >= k && a[i] < T  

      ans += left。理由同上。

3.bigger < k && a[i] >= T  

      bigger++,{如果bigger==k(有效区间中大于等于T数量为k,正好成为好区间),将left右移至a[left] >= T。 ans+= left。理由同上。}

4.bigger < k && a[i] < T

      不做处理,因为bigger,left,ans都没变。

 

 

代码:

#include <bits\stdc++.h>using namespace std;typedef long long ll;ll n,k,T,b,c,p;ll a[10000001];int main(){    cin >> n >> k >> T >> a[0] >> b >> c >> p;    int bigger = 0;    int left = 1;    ll ans = 0;    for(int i = 1;i <= n; i++){        a[i] = (a[i-1]*b+c)%p;//        cout << a[i] << " ";        if(bigger >= k){            if(a[i] >= T){                  bigger++;                int c = 1;                    for(int j = left;j <= i; j++){                    if(a[j] < T){ left++;continue;}                    else if(c > 0){ left++,c--;continue; }                    break;                }                ans += left;            }else{                ans += left;            }         }else{            if(a[i] >= T){                  bigger++;                  if(bigger == k){                      for(int j = left;j <= i; j++){                        if(a[j] < T){ left++;continue;}                        break;                    }                    ans += left;                }            }        }//        cout << ans << endl;    }    cout << ans << endl;    return 0;} //writed by zhangjiuding

 

阅读全文
0 0
原创粉丝点击