5 2 -2 0 2 0 -2 0 5 2 3 2 3 3 3 3
12 5
题意:给你一个序列b1,b2,⋯,bn,问有多少个区间[l,r]满足该区间存在一个i,使得[l,i]是以d1为公差的等差数列,[i,r]是以d2为公差的等差数列
解题思路:老办法,观察样例吧,第一个样例的取法是{0},{0,2},{0,2,0},{0,2,0,-2},{2},{2,0},{2,0,-2},{0},{0,-2},{-2},{-2,0},{0}共12种由此可见我们只需先找出满足题意的区间[l,r],知道里面序列的个数k,那么该区间的情况数为
但是有一点不能忽略,即一个元素bi,若它既属于前一个区间,又属于后一个区间的话,它本身会被多计算一次,比如样例1中的-2,它既属于区间[1,4],又属于区间[4,5],那么若单纯带公式再相加,那么取法{-2}会被计算两次,所以解题的时候判断一下,减去多算的即为结果。
放上一组样例以供参考
Input
5 2 2
0 2 0 2 4
Output
9
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<math.h> #include<vector> #include<map> #include<set> #include<stdlib.h> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 100005; const int inf = 1000000000; const int mod = 258280327; int s[N]; int main() { int n,d1,d2,i,t,j,sum; __int64 ans,k; while(~scanf("%d%d%d",&n,&d1,&d2)) { t=1;sum=j=0;k=1;ans=0; for(i=1;i<=n;i++) scanf("%d",&s[i]); for(i=1;i<n;i++) { if(t) { if(s[i]+d1==s[i+1]) k++; else t=0; j=0; } if(!t) { if(s[i]+d2==s[i+1]) { k++; j++; } else { ans+=(k+1)*k/2; if(sum+k>i) ans--; //printf("%d\n",k); k=1; t=1; sum=i; if(j) i--; } } } ans+=(k+1)*k/2; if(sum+k>i) ans--; //printf("%d\n",k); printf("%I64d\n",ans); } return 0; }菜鸟成长记