hdu2227 && hdu3450 【树状数组优化dp】
2013-04-17 00:03
357 查看
hdu2227
树状数组的一个经典应用。
容易得到dp方程,dp[pos]表示前pos项里以a[pos]结尾的非降子序列的个数。
则有dp[pos]=sum( dp[i] , 1<= i <pos && a[i]<=a[pos] ) + 1。
复杂度为O(n^2),Time Limit Exceeded!!!
观察到a[i]<=a[pos] , 我们对原序列a从小到大排序,得到新的序列d,对d进行dp。
此时dp[pos]=sum(dp[i],1<=i<pos && d[i]的原序在d[pos]的原序之前 ) + 1。
对于元素d[pos] , d[1],...,d[pos-1]都<=d[pos],但是这些元素的原序可能在d[i]之后,而dp[i]只能依赖原序在d[i]之前的值来更新。
怎么解决这个问题呢?
我们对原序列a中的元素依次访问 , 记为a[i] , 并对应至d中相应的元素d[k](?) , 更新dp[k]=sum( dp[j] , 1<= j <k ) + 1。
为什么不用考虑顺序的问题了?因为此时只有原序在d[k]之前的元素被更新过。
而求和操作可以利用树状数组来实现。
(?)这里可以发现,a[i]到d[k]的对应是有问题的,这里用到了离散化( 排序,去重,二分对应标号 )。(ps:其实离散化这个概念我刚接触,也还不太懂。。。希望懂的人不吝赐教)
//另外,当a[i]范围比较小时,可以不用离散化,直接以a[i]的值作为对应标号即可。
这样,这个问题在O(nlogn)的复杂度下Accepted了。
View Code
树状数组的一个经典应用。
容易得到dp方程,dp[pos]表示前pos项里以a[pos]结尾的非降子序列的个数。
则有dp[pos]=sum( dp[i] , 1<= i <pos && a[i]<=a[pos] ) + 1。
复杂度为O(n^2),Time Limit Exceeded!!!
观察到a[i]<=a[pos] , 我们对原序列a从小到大排序,得到新的序列d,对d进行dp。
此时dp[pos]=sum(dp[i],1<=i<pos && d[i]的原序在d[pos]的原序之前 ) + 1。
对于元素d[pos] , d[1],...,d[pos-1]都<=d[pos],但是这些元素的原序可能在d[i]之后,而dp[i]只能依赖原序在d[i]之前的值来更新。
怎么解决这个问题呢?
我们对原序列a中的元素依次访问 , 记为a[i] , 并对应至d中相应的元素d[k](?) , 更新dp[k]=sum( dp[j] , 1<= j <k ) + 1。
为什么不用考虑顺序的问题了?因为此时只有原序在d[k]之前的元素被更新过。
而求和操作可以利用树状数组来实现。
(?)这里可以发现,a[i]到d[k]的对应是有问题的,这里用到了离散化( 排序,去重,二分对应标号 )。(ps:其实离散化这个概念我刚接触,也还不太懂。。。希望懂的人不吝赐教)
//另外,当a[i]范围比较小时,可以不用离散化,直接以a[i]的值作为对应标号即可。
这样,这个问题在O(nlogn)的复杂度下Accepted了。
View Code
//hdu3450 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100005,MOD = 9901; int a ,b ,hash ,c ,tot; int lowbit(int x) {return x&(-x);} void add(int id,int x) { for(int i=id;i<=tot;i+=lowbit(i)) c[i]= (c[i]+x)%MOD; } int query(int id) { int sum=0; for(int i=id;i>=1;i-=lowbit(i)) sum = (sum+c[i])%MOD; return sum; } int findR(int v) { int i=1,j=tot+1,mid; while( i<j ) { mid=(i+j)/2; if( hash[mid]<=v ) i=mid+1; else j=mid; } return i-1; } int findL(int v) { int i=1,j=tot+1,mid; while( i<j ) { mid=(i+j)/2; if( hash[mid]<v ) i=mid+1; else j=mid; } return i-1; } int main() { int n,d; while( ~scanf("%d%d",&n,&d) ) { for(int i=1;i<=n;i++) { scanf("%d",&a[i]); b[i]=a[i]; } sort(b+1,b+n+1); tot=1; hash[1]=b[1]; for(int i=2;i<=n;i++) if( b[i]!=b[i-1] ) hash[++tot]=b[i]; memset(c+1,0,tot*sizeof(c[0])); for(int i=1;i<=n;i++) { int L=findL(a[i]-d),id=findL(a[i])+1,R=findR(a[i]+d); int tmp=query(R)-query(L); add(id,tmp+1); } printf("%d\n",((query(tot)-n)%MOD+MOD)%MOD); } return 0; }
相关文章推荐
- 2015 Multi-University Training Contest 10 (hdu 5406-5416)数据结构+dp+矩阵快速幂+bitset优化拓扑排序+(dp&树状数组)
- [DP] [1D1D优化] [树状数组] [最短路] 遭遇战 (clean)
- 树状数组优化dp——nkoj3771公共汽车
- 【扩展KMP】【树状数组优化dp】字符串游戏
- 【HDU4991】dp 树状数组优化
- Codeforces 597C Subsequences 【树状数组优化DP】
- bzoj 3594: [Scoi2014]方伯伯的玉米田 二维树状数组优化dp
- hdoj 2227 Find the nondecreasing subsequences 【树状数组优化dp】
- 【数位dp && 优化数组范围】CodeForces - 55D Beautiful numbers
- hdoj 3450 Counting Sequences 【离散化 + 树状数组优化dp】
- hdu 3450(树状数组优化dp)
- bzoj4361 isn(树状数组优化DP)
- hdu 4991(树状数组优化dp)
- BZOJ 3594 方伯伯的玉米田 (二维树状数组优化dp)
- BZOJ3594[Scoi2014] 方伯伯的玉米田 解题报告【二维树状数组优化DP】
- 树状数组优化DP 【模拟赛】删区间
- [BZOJ3594] [Scoi2014]方伯伯的玉米田 二维树状数组优化dp
- BZOJ3594 二维树状数组优化DP
- [BZOJ2131]免费的馅饼-树状数组优化DP
- CodeForces 602E【概率DP】【树状数组优化】