2010 ACM-ICPC Multi-University Training Contest(2)——Host by BUPT

依然是树状数组+离散化+dp

http://acm.hdu.edu.cn/showproblem.php?pid=3450



AC

#include<iostream> #include<cstdio> #include<string.h> #include<algorithm> #define N 100005 #define M 9901 using namespace std; typedef long long L; int kp[N]; int a[N]; int s[N]; int n,m; int tot; inline int lowbit(int x) {return x&(-x);} void update(int x,int v) { while(x<N) { s[x]+=v; if(s[x]>=M) s[x]%=M; x+=lowbit(x); } } L Quary(int x) { L sum=0; while(x>0) { sum+=s[x]; if(sum>=M) sum%=M; x-=lowbit(x); } return sum; } int lisan(int x) { int l=1,r=tot; while(l<=r) { int mid=(l+r)>>1; if(a[mid]==x) return mid; else if(a[mid]>x) r=mid-1; else if(a[mid]<x) l=mid+1; } return -1; } int lisanlift(int x) { int l=1,r=tot; int ans=0; while(l<=r) { int mid=(l+r)>>1; if(a[mid]>=x)//找到比x大的最小的那个数 { r=mid-1; ans=mid; } else l=mid+1; } return ans; } int lisanright(int x) { int l=1,r=tot; int ans=0; while(l<=r) { int mid=(l+r)>>1;//找到比x小的最大的那个数 if(a[mid]<=x) { l=mid+1; ans=mid; } else r=mid-1; } return ans; } int main() { while(~scanf("%d%d",&n,&m)) { memset(s,0,sizeof(s)); tot=0; for(int i=1;i<=n;++i) { scanf("%d",&kp[i]); a[i]=kp[i]; } sort(a+1,a+n+1); for(int i=1;i<=n;++i) if(i==1||(a[i]!=a[i-1])) a[++tot]=a[i]; L res=0; for(int i=1;i<=n;++i) { int num=lisan(kp[i]); int l=lisanlift(kp[i]-m); int r=lisanright(kp[i]+m); L k=Quary(r)-Quary(l-1); if(k<0) k+=M; if(k>=M) k%=M; res+=k+1; if(res>=M) res%=M; update(num,k+1); } printf("%d\n",((res-n)%M+M)%M); }return 0; }
题意:找一共有多少个这样的序列(length>=2),保证相邻的两个数的绝对值不超过d:
思路:以每个值为基准点找到大于x-d最小的数a,和小于x+d的最大数b,那么就可已找到一共有多少可满足区间[x-d,x+d]的数。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值