HDU 5400 Arithmetic Sequence(左d1等差右d2等差的区间个数)(枚举位置,求最大区间,算区间个数)

Arithmetic Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 636    Accepted Submission(s): 285


Problem Description
A sequence  b1,b2,,bn  are called  (d1,d2) -arithmetic sequence if and only if there exist  i(1in)  such that for every  j(1j<i),bj+1=bj+d1  and for every  j(ij<n),bj+1=bj+d2 .

Teacher Mai has a sequence  a1,a2,,an . He wants to know how many intervals  [l,r](1lrn)  there are that  al,al+1,,ar  are  (d1,d2) -arithmetic sequence.
 

Input
There are multiple test cases.

For each test case, the first line contains three numbers  n,d1,d2(1n105,|d1|,|d2|1000) , the next line contains  n  integers  a1,a2,,an(|ai|109) .
 

Output
For each test case, print the answer.
 

Sample Input
  
  
5 2 -2 0 2 0 -2 0 5 2 3 2 3 3 3 3
 

Sample Output
  
  
12 5
 

Author
xudyh
 

Source
 


题目大意:给出n,d1,d2,再给出n个数的序列,问有多少区间[l,r](1<=l<=r<=n),使得存在i(l<=i<=r),满足当l<=j<i时,b[j+1]=b[j]+d1;当i<j<=r时,b[j+1]=b[j]+d2。


解题思路:枚举i(1<=i<=n),预处理出以i为中心,左侧是满足以d1为公差的等差数列的最大长度l[ i ],右侧是满足以d2为公差的等差数列的最大长度r[ i ],那么以i为一个解的区间个数为l[ i ]*r[ i ]。

预处理过程:

1、预处理l[ ],如果i的左侧紧邻的数不满足条件,则l[i]值是1(即它本身就可以),而l[i]的值与l[i-1]的值是有关系的,如果b[i]-b[i-1]=d1,那么l[i]=l[i-1]+1;否则,l[i]=1。

2、预处理r[ ],如果i的右侧紧邻的数不满足条件,则r[i]的值是1;如果i的右侧紧邻的数满足条件,则r[i]的值与r[i+1]的值是有关系的,如果b[i+1]-b[i]=d2,则r[i]=r[i+1]+1;否则,r[i]=1。


代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-6)
#define inf (1<<28)
#define sqr(x) (x) * (x)
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
const int MAX = 100005;
int main()
{
    int i,n,d1,d2;
    int a[MAX],l[MAX],r[MAX];
    while(~scanf("%d%d%d",&n,&d1,&d2))
    {
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(i=0;i<n;i++)
        {
            if(i==0||(a[i]-a[i-1])!=d1)
                l[i]=1;
            else
                l[i]=l[i-1]+1;
        }
        /*
        for(i=0;i<n;i++)
            printf("%d ",l[i]);
        printf("\n");
        */
        for(i=n-1;i>=0;i--)
        {
            if(i==(n-1)||(a[i+1]-a[i])!=d2)
                r[i]=1;
            else
                r[i]=r[i+1]+1;
        }
        /*
        for(i=0;i<n;i++)
            printf("%d ",r[i]);
        printf("\n");
        */
        ll ans=0;
        for(i=0;i<n;i++)
        {
            if(d1!=d2)
                ans+=(ll)l[i]*r[i];
            else
                ans+=r[i];
        }
        printf("%I64d\n",ans);
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值