//CodeForces 314C
//分析:相当于求给定序列的不降子序列的个数,从一个空序列开始将得到的不降子序列不断的延长是典型的做法,则dp[i]表示以第 i 个元素结尾的序列
//思路:O(n^2) 的做法,dp[i] = sum(dp[j]]) (a[j] <= a[i] && j <= i),求和过程用掉了 O(n) 的复杂度,用树状数组可以优化成 O(logn),需要先处理出每个元素在原来的序列中的大小顺序,最终复杂度 O(nlogn)。
1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 using namespace std; 6 int n; 7 struct st 8 { 9 int ans, rank, pos; 10 } a[100010]; 11 int tot; 12 bool cmp_1(st a, st b) 13 { 14 return a.ans < b.ans; 15 } 16 bool cmp_2(st a, st b) 17 { 18 return a.pos < b.pos; 19 } 20 21 inline int lowbit(int p) 22 { 23 return p&-p; 24 } 25 const int mod = 1000000007; 26 27 const int maxn = 100010; 28 int t[maxn], element[maxn]; 29 void add(int p, int x) 30 { 31 int i; 32 for(i = p; i <= tot; i += lowbit(i)) { 33 t[i] += x; 34 t[i] %= mod; 35 } 36 } 37 38 __int64 sum(int p) 39 { 40 int i, res = 0; 41 for(i = p; i >= 1; i -= lowbit(i)) { 42 res += t[i]; 43 res %= mod; 44 } 45 return res; 46 } 47 48 int main() 49 { 50 int i, j; 51 scanf("%d", &n); 52 for(i = 1; i<=n; ++i) { 53 scanf("%d", &a[i].ans); 54 a[i].pos = i; 55 } 56 sort(a+1, a+1+n, cmp_1); 57 tot = 1; 58 a[1].rank = 1; 59 for(i = 2; i<=n; ++i) { 60 if(a[i].ans!=a[i-1].ans) 61 a[i].rank = ++tot; 62 else 63 a[i].rank = tot; 64 } 65 sort(a+1, a+1+n, cmp_2); 66 int tmp; 67 for(i = 1; i<=n; ++i) { 68 tmp = (sum(a[i].rank)*a[i].ans%mod+a[i].ans)%mod; //a[i].ans 是对空串的延长,因为 树状数组 不能计算到 t[0],不然就不用特殊处理空串的情况了 69 add(a[i].rank, (tmp-element[a[i].rank]+mod)%mod); //减去重复计算值,即上一次的计算值 70 element[a[i].rank] = tmp; //记录上一次的计算值 71 } 72 printf("%d\n", sum(tot)); 73 }
时间: 2024-10-14 13:29:28