CodeForces - 597C:Subsequences (主席树+DP)
For the given sequence with n different elements find the number of increasing subsequences with k + 1 elements. It is guaranteed that the answer is not greater than 8·1018.
Input
First line contain two integer values n and k (1 ≤ n ≤ 105, 0 ≤ k ≤ 10) — the length of sequence and the number of elements in increasing subsequences.
Next n lines contains one integer ai (1 ≤ ai ≤ n) each — elements of sequence. All values ai are different.
Output
Print one integer — the answer to the problem.
Examples
Input
5 2
1
2
3
5
4
Output
7
题意:求多少个LIS,其长度为K+1。
思路:用dp[k][x]表示以x结尾的长度为k的LIS。那么暴力的DP复杂度是O(N^2)。
建立k棵线段树,每棵树N个叶子节点,第i棵树的第j个叶子节点表示以j为结尾的长度为i的LIS个数。 那么Tree[i][j]+=Tree[i-1][1到j-1]。
(直接写线段树也可以,这里练习一下主席树。 当然最好写的还是树状数组!
相比的话,主席树应该还是好写的。
#include<bits/stdc++.h> typedef long long ll; using namespace std; const int maxn=100010; int rt[maxn],cnt; ll ans; struct node { int l,r; ll val; node(){ l=r=0;val=0;} node(int L,int R,ll V):l(L),r(R),val(V){} }s[maxn*30]; ll query(int Now,int L,int R,int l,int r) { if(l<=L&&r>=R) return s[Now].val; ll res=0; int Mid=(L+R)>>1; if(l<=Mid) res+=query(s[Now].l,L,Mid,l,r); if(r>Mid) res+=query(s[Now].r,Mid+1,R,l,r); return res; } void update(int &Now,int L,int R,int pos,ll val) { if(Now==0) Now=++cnt; s[Now].val+=val; if(L==R) return ; int Mid=(L+R)>>1; if(pos<=Mid) update(s[Now].l,L,Mid,pos,val); else update(s[Now].r,Mid+1,R,pos,val); } int main() { int N,K,i,j,x; scanf("%d%d",&N,&K); for(i=1;i<=N;i++){ scanf("%d",&x); x+=2; update(rt[1],1,N+2,x,1); for(j=0;j<=K;j++) { ll tmp=query(rt[j],1,N+2,1,x-1); update(rt[j+1],1,N+2,x,tmp); } } ans=query(rt[K+1],1,N+2,1,N+2); printf("%I64d\n",ans); return 0; }
It is your time to fight!