51nod 1495 中国好区间

本文介绍了一种使用尺取法和前缀和解决特定类型问题的方法。通过两个指针定义区间,利用前缀和快速计算区间内大于某个阈值T的元素数量是否满足条件。该技巧在解决序列中寻找符合条件的子段问题时非常有效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1495&judgeId=519564
这道题给我说了尺取法我也不会,没办法只能看别人的博客(;´д`)ゞ
感觉弄得好巧妙啊~

①首先,条件是选取的长度大于等于 K K 这个好理解,就他的两个指针 RL+1>=K 就行了。
②但是要求从大到小第 K K 大的数要大于T,哇~这个就挺巧妙的了,转换成比 T T 大的有K个,然后就又是前缀和,用一个 sum[i] s u m [ i ] 表示从 1 1 i大于等于 T T 的个数,那么[L,R]中的就是 sum[R]sum[L1] s u m [ R ] − s u m [ L − 1 ] ,只要 sum[R]sum[L1]>=K s u m [ R ] − s u m [ L − 1 ] >= K 就满足条件

③然后计算答案时,就是用的尺取法的关键了,只要哪一个 [L,R] [ L , R ] 满足条件那么后面的 [L,R+1],[L,R+2],,,, [ L , R + 1 ] , [ L , R + 2 ] , , , , 一直到 [L,N] [ L , N ] 都是满足条件的,于是就阔以直接算出有 NR+1 N − R + 1 个了

#include"iostream"
using namespace std;
const int maxn=1e7+5;
long long a[maxn],sum[maxn];//sum用来记录前i个大于T的有多少个
int main()
{
    long long N,K,T,b,c,p;
    while(cin>>N>>K>>T>>a[0]>>b>>c>>p)
    {
        long long ans=0;
        for(int i=1;i<=N;i++)
        {
            a[i]=(a[i-1]*b+c)%p;
            sum[i]=sum[i-1];
            if(a[i]>=T)sum[i]++;//②
        }
        int L=1,R=1;
        while(1)
        {
            while(R<=N&&sum[R]-sum[L-1]<K)R++;//①
            if(R>N)break;
            ans+=N-R+1;//③
            L++;
        }
        cout<<ans<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值