[树状数组+DP]hdu3450 Counting Sequences
2015-08-27 11:25
405 查看
题意:
找出所有的美丽序列。美丽序列就是相邻的元素绝对值之差不超过d的序列。
分析:
dp[i]表示到i为止满足情况的种类数。
dp[i]=sum(dp[j] abs(a[j]-a[i])<=d);
当然这个数据量很大,直接按照方程的话复杂度为O(n*n). 所以要利用其他方式,树状数组。这里需要对元素离散化,因为d很大。刚开始想的时候以为二维的DP可以,但是存储空间不允许。后来一直不明白的问题是如何证明:
dp[i]=sum(dp[j] abs(a[j]-a[i])<=d);
假如 1 3 5 7 满足序列,那么美丽序列就有{1,3}{3,5}{5,7}{1,3,5}{3,5,7}{1,3,5,7} 分别为两个元素的情况,三个元素的情况,四个元素的情况。当然我们数的时候会这样想,但是计算的时候就不能这样想了。首先加入树状数组之前,先求出满足条件的种类数,那么这个数就要加入到这些合法的序列后面才合法,而这些合法的序列的由来又有很多种方式+1(只有自己),所以结果还是递推出来的。
找出所有的美丽序列。美丽序列就是相邻的元素绝对值之差不超过d的序列。
分析:
dp[i]表示到i为止满足情况的种类数。
dp[i]=sum(dp[j] abs(a[j]-a[i])<=d);
当然这个数据量很大,直接按照方程的话复杂度为O(n*n). 所以要利用其他方式,树状数组。这里需要对元素离散化,因为d很大。刚开始想的时候以为二维的DP可以,但是存储空间不允许。后来一直不明白的问题是如何证明:
dp[i]=sum(dp[j] abs(a[j]-a[i])<=d);
假如 1 3 5 7 满足序列,那么美丽序列就有{1,3}{3,5}{5,7}{1,3,5}{3,5,7}{1,3,5,7} 分别为两个元素的情况,三个元素的情况,四个元素的情况。当然我们数的时候会这样想,但是计算的时候就不能这样想了。首先加入树状数组之前,先求出满足条件的种类数,那么这个数就要加入到这些合法的序列后面才合法,而这些合法的序列的由来又有很多种方式+1(只有自己),所以结果还是递推出来的。
[code] #include<iostream> #include<stdio.h> #include<math.h> #include<utility> #include <map> #include<cstring> #include<vector> #include<deque> #include<queue> #include<stack> #include<algorithm> #include<stdlib.h> #define read freopen("q.txt","r",stdin) #define LL long long const int maxn =100005; const double inf=2000000000.0; const int mod=9901; using namespace std; int c[maxn],a[maxn],hs[maxn]; int cnt,n; int lowbit(int x) { return x&(-x); } int getSum(int x) { int sum=0; for(int i=x;i>0;i-=lowbit(i)) { sum+=c[i]; sum%=mod; } return sum; } void update(int x,int val) { for(int i=x;i<=n;i+=lowbit(i)) { c[i]+=val; } } int low(int x) { int l=1,r=cnt; while(l<=r) { int mid=(l+r)/2; if(hs[mid]<x)l=mid+1; else r=mid-1; } return r+1; } int up(int x) { int l=1,r=cnt; while(l<=r) { int mid=(l+r)/2; if(hs[mid]<=x)l=mid+1; else r=mid-1; } return l-1; } int main() { int d,i,j; while(~scanf("%d%d",&n,&d)) { memset(c,0,sizeof(c)); for(i=1;i<=n;i++) { scanf("%d",a+i); hs[i]=a[i]; } sort(hs+1,hs+n+1); cnt=1; for(i=2;i<=n;i++)if(hs[i]!=hs[cnt])hs[++cnt]=hs[i]; int sum=0; for(i=1;i<=n;i++) { int x=low(a[i]-d),y=up(a[i]+d),z=low(a[i]); int tmp=getSum(y)-getSum(x-1); tmp+=mod; tmp%=mod; /////////////// cout<<"TTTTmp = "<<tmp<<endl; sum=(sum+tmp)%mod; update(z,tmp+1); // cout<<"sum = "<<sum<<endl; } cout<<sum<<endl; } }
相关文章推荐
- iOS开发UI篇—常见的项目文件介绍
- Gym 100641A Continued Fractions || 简单数学题
- Java____序列化private static final long serialVersionUID的作用
- easyui validatebox 验证类型
- UIView的layoutSubviews和drawRect
- [SoapUI] Jenkins 配置
- JAX-RS @QueryParam example
- 【第十一篇】这一篇来说说MVC+EF+easyui datagrid的查询功能
- 获取电脑的开机时间NtQuerySystemInformation
- 如何在Ubuntu平台上使用Bluetooth
- 一、buildroot-2014.08编译根文件系统(nfs挂载)
- [leetcode] 63.Unique Paths II
- poj-2442Sequence
- UITextfield键盘相关设置
- uedit富文本编辑器
- [leetcode] 62.Unique Paths
- 国内UED大全
- HDU3836Equivalent Sets(强连通+加边构成强连通)
- UISegmentedControl
- codeforces 487C C. Prefix Product Sequence(数论+构造)