思路:这题就是求这个序列中有多少个上升序列,如果按照一般的思路去for...for...for...的话,必然是超时的,所以这时候就需要减少时间上的复杂度,首先,dp[i] = ∑dp[k] (a[i] > a[k] && i > k),这样我们在往后面扫的时候需要快速的求出前面的和也就是等式右边的部分,这个当然就是线段树去完成了,由于单个数很大,只能离散化,还好n不大,离散化下来的话也就是n个数。
// #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; // #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__ ) #else #define debug(...) #endif #define CLR(x) memset(x, 0,sizeof x) #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back template<class T> inline T Get_Max(const T&a,const T&b){return a < b?b:a;} template<class T> inline T Get_Min(const T&a,const T&b){return a < b?a:b;} typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; const int maxn = 1e5 + 10; struct Node{ int val, pos; }q[maxn], p[maxn]; bool cmp(const Node& A,const Node& B){ return A.val < B.val; } int A[maxn]; int dp[maxn<<2]; int n; inline void InitRead(){ for (int i = 1;i <= n;++i){ scanf("%d",&q[i].val); q[i].pos = i; } sort(q+1,q+1+n,cmp); int pre = q[1].val; p[1].val = 1,p[1].pos = q[1].pos; for (int i = 2;i <= n;++i){ if (q[i].val == pre){ p[i].val = p[i-1].val; }else{ p[i].val = p[i-1].val + 1; } pre = q[i].val; p[i].pos = q[i].pos; } for (int i = 1;i <= n;++i){ A[p[i].pos] = p[i].val; } } void up(int rt){ dp[rt] = dp[rt<<1]+dp[rt<<1|1]; dp[rt] %= MOD; } void build(int rt,int L,int R){ if (L==R){ dp[rt] = 0; return; } int mid = (L+R)/2; build(rt<<1,L,mid); build(rt<<1|1,mid+1,R); up(rt); } void updata(int loc,int addv,int rt,int L,int R){ if (L == R && R == loc){ dp[rt] += addv; dp[rt] %= MOD; return; } int mid = (L+R)/2; if (loc <= mid) updata(loc, addv,rt<<1,L,mid); else updata(loc, addv,rt<<1|1,mid+1,R); up(rt); return; } int Query(int l,int r,int rt,int L,int R){ if (l > r) return 0; if (l <= L && R <= r){ return dp[rt]; } int mid = (L+R)/2; int ans = 0; if (l <= mid) ans += Query(l,r,rt<<1,L,mid),ans %= MOD; if (r > mid) ans += Query(l,r,rt<<1|1,mid+1,R), ans %= MOD; up(rt); return ans; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int t; int icase = 0; scanf("%d",&t); while(t--){ scanf("%d",&n); InitRead(); build(1,1,n); int ans = 0; for (int i = 1;i <= n;++i){ int tmp = Query(1,A[i]-1,1,1,n) + 1; ans += tmp; ans %= MOD; updata(A[i],tmp,1,1,n); } printf("Case %d: %d\n",++icase, ans); } return 0; }