「 HDOJ P2227 」 Find the nondecreasing subsequences
# 题目大意
就是找不下降子序列的个数。
# 解题思路
一开始想着先离散化,然后再做个 $dp$,发现用 $dp$ 的话时间复杂度是 $\text{O}(n^2)$ 的,稳稳超时。
这里说说 $dp$:
设 $dp[i]$ 表示以 $a[i]$ 为结尾的不下降子序列的个数。
那么状态转移方程就显而易见了:
$$dp[i] = sum(dp[j])+1,a[j]<=a[i]\&\&j<i$$
遂放弃 $dp$,转向另一种思路:树状数组。
因为要求逆序列的个数。所以选择用树状数组来做,思路如下:
将数据离散化后,按照原来输入的顺序从小到大将每一个数的影响加到树状数组中。那么影响是啥?
就是会对当前这个数后面的比它大的数字造成影响,因为会构成逆序列。然后你就牛逼了。。。
这样的话,每次询问一个数时,只有它前面的数的影响才被加了进去。就可以保证询问的正确性。
# 附上代码
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 1e5+3, HA = 1e9+7; int n, s[maxn], a[maxn], tmp[maxn], bit[maxn], NI[maxn]; inline int lowbit(int x) {return x & -x;} inline void add(int pos, int num) { while (pos <= n) { bit[pos] = ((num % HA) + (bit[pos] % HA)) % HA; pos += lowbit(pos); } } inline int query(int pos) { int res = 0; while (pos >= 1) { res = ((bit[pos] % HA) + (res % HA)) % HA; pos -= lowbit(pos); } return res; } int main() { while (~scanf("%d", &n)) { memset(NI, 0, sizeof(NI)); memset(bit, 0, sizeof(bit)); for(int i=1; i<=n; i++) { scanf("%d", &s[i]); tmp[i] = s[i]; } sort(tmp+1, tmp+1+n); for(int i=1; i<=n; i++) a[i] = lower_bound(tmp+1, tmp+1+n, s[i])-tmp; for(int i=1; i<=n; i++) { NI[i] = query(a[i]); NI[i] %= HA; add(a[i], NI[i] + 1); } printf("%d\n", query(n)); } }
作者:Mystical-W
来源:http://www.cnblogs.com/bljfy
说明:客官~~您如果觉得写得好的话,记得给我点赞哦。如果要转载的请在合适的地方注明出处。谢
谢您的合作。您要是有什么有疑问的地方可以在下面给我评论。也可以直接私信我哦
声明:本作品由Mystical-W采用知识共享署名-非商业性使用-禁止演绎 4.0 国
际许可协议进行许可
来源:http://www.cnblogs.com/bljfy
说明:客官~~您如果觉得写得好的话,记得给我点赞哦。如果要转载的请在合适的地方注明出处。谢
谢您的合作。您要是有什么有疑问的地方可以在下面给我评论。也可以直接私信我哦
声明:本作品由Mystical-W采用知识共享署名-非商业性使用-禁止演绎 4.0 国
际许可协议进行许可