和前面一題差不多的思路。但是這題要做的處理多一點。
題意:相鄰兩個數之和<=d.給出一個序列計算出符合要求的序列個數。
abs(a[i]-a[j])<=d
d-a[i]<=a[j]<=d+a[i]
找到大於a[i]-d的最大數L,
找到小於a[i]+d的最大數R
求出[L,R]之間小於等於H的數。
/*Problem ID:meaning:Analyzing:*/#include <iostream>#include <algorithm>#include<cstdio>#include<cmath>#include<cstdlib>#include<cstring>#include<vector>using namespace std;typedef struct even{int y1,y2,x;}even;#define clr(A,k) memset(A,k,sizeof(A))#define FOR(i,s,t) for(int i=(s); i<(t); i++)#define LL long long#define BUG puts("here!!!")#define print(x) printf("%d\n",x)#define STOP system("pause")#define eps 1e-8#define PI acos(-1.0)#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define maxn 100006#define maxm 1005#define MOD 9901#define lowbit(x) x&(-x)LL gcd(LL a,LL b) {return a?gcd(b%a,a):b;}int n,d,len;int C[maxn],A[maxn],S[maxn];void update(int pos,int val){ while(pos<=len){ C[pos]+=val; if(C[pos]>=MOD) C[pos]%=MOD; pos+=lowbit(pos); }}int query(int x){ int sum=0; while(x>0){ sum+=C[x]; if(sum>=MOD) sum%=MOD; x-=lowbit(x); } return sum;}int BinLeft(int left){ int l=1,r=len,ans=0; while(l<=r){ int m=(l+r)>>1; if(S[m]>=left){ ans=m; r=m-1; } else { l=m+1; } } return ans;}int BinRight(int right){ int l=1,r=len,ans=len; while(l<=r){ int m=(l+r)>>1; if(S[m]<=right){ ans=m; l=m+1; } else { r=m-1; } } return ans;}int BinSearch(int x){ int l=1,r=len; while(l<=r){ int m=(l+r)>>1; if(S[m]==x) return m; if(S[m]>x) r=m-1; else l=m+1; }}int main(){ int n; while(~scanf("%d%d",&n,&d)){ for(int i=1;i<=n;i++){ scanf("%d",&A[i]); S[i]=A[i]; } sort(S+1,S+n+1); len=2; for(int i=2;i<=n;i++){ if(S[i]!=S[i-1]) S[len++]=S[i]; } clr(C,0); int sum=0; for(int i=1;i<=n;i++){ int id=BinSearch(A[i]); // cout<<"ID :"<<id<<endl; int left=BinLeft(A[i]-d);//找到比A[i]-d大的最小數 // cout<<"left:"<<left<<endl; int right=BinRight(A[i]+d); LL tmp=query(right)-query(left-1); // cout<<"tmp : "<<tmp<<endl; if(tmp<0) tmp+=MOD; if(tmp>=MOD) tmp%=MOD; sum+=tmp+1; if(sum>=MOD) sum%=MOD; update(id,tmp+1); } sum=((sum-n)%MOD+MOD)%MOD; printf("%d\n",sum); }return 0;}