标签:元素 ext uniq code 保留 重复元素 std div cal
Description
Input
Output
Sample Input
4 2 1 3 7 5
Sample Output
4
【题意】给一个数字序列,问长度大于2的且相邻两个数的差的绝对值不大于d的情况对9901取余
【思路】对于当前的数A,那么以它为最后一个元素可以组成的情况是A-d到A+d的和,也可以这样想,A-d的已经组成了m种情况,那么在不影响小于d的情况下,可以直接将A放到A-d组成的左右序列中,那么直接加就可以了,而后更新A可以组成的情况,数据太大还需要离散化,然后二分找一下A-d和A+d的位置,数据可能没有这两个位置,那么找到第一个大于等于A-d和第一个小于等于A+d的位置更新就行,且不会影响结果。
参考:http://blog.csdn.net/dan__ge/article/details/51620024
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=100000+10; const int mod=9901; int a[N],x[N],sum[4*N]; int n,m,nn,cnt; void build(int k,int l,int r)//建树 { sum[k]=0; if(l==r) return ; int mid=l+r>>1; build(2*k,l,mid); build(2*k+1,mid+1,r); } void update(int ll,int rr,int k,int l,int r) { if(l==r) { sum[k]=(sum[k]+rr)%mod; return ; } int mid=l+r>>1; if(mid>=ll) update(ll,rr,k*2,l,mid); if(mid<ll) update(ll,rr,k*2+1,mid+1,r);// sum[k]=(sum[k*2]+sum[k*2+1])%mod; } int query(int ll,int rr,int k,int l,int r) { if(ll<=l&&r<=rr) return sum[k]%mod; int mid=l+r>>1; int res=0; if(ll<=mid) res+=query(ll,rr,k*2,l,mid); if(mid<rr) res+=query(ll,rr,k*2+1,mid+1,r); return res%mod; } int main() { while(~scanf("%d%d",&n,&m)) { cnt=0; for(int i=0;i<n;i++) { scanf("%d",&a[i]); x[cnt++]=a[i]; x[cnt++]=a[i]-m; x[cnt++]=a[i]+m; } sort(x,x+cnt); nn=unique(x,x+cnt)-x;//nn去重后,不重复元素的个数;STLunqiue在STL中unique函数是一个去重函数,unique的功能是去除相邻的重复元素(只保留一个),
//其实它并不真正把重复的元素删除,是把重复的元素移到后面去了,然后依然保存到了原数组中,然后 返回去重后最后一个元素的地址,
//因为unique去除的是相邻的重复元素,所以一般用之前都会要排一下序。 build(1,1,nn); int ans=0; for(int i=0;i<n;i++) { int p=lower_bound(x,x+nn,a[i])-x;//Lower_bound是小于等于关键字的位置 int left=lower_bound(x,x+nn,a[i]-m)-x; int right=lower_bound(x,x+nn,a[i]+m)-x; int c=query(left+1,right+1,1,1,nn); update(p+1,c+1,1,1,nn); ans=(ans+c)%mod; } printf("%d\n",ans); } return 0; }
标签:元素 ext uniq code 保留 重复元素 std div cal
原文地址:http://www.cnblogs.com/iwantstrong/p/6057524.html