-
C - K-inversions
URAL - 1523 - 题意:给出一个1-n的排列求一下长度为k的 位置与数值满足这个关系的 子序列个数:
- 1 ≤ i 1 < i 2 < … < ik ≤ n and ai 1 > ai 2 > … > aik.
- 思路:dp转移,dp[i][j] i 代表新的长度为k的序列中第i个数 , j代表的是原来长度为n序列中第j个数
- 存的值是方案数,这个位置的方案数可以有上一个位置的方案数,求和得到,前面位置那些数
- 目前按顺序访问已经满足了,位置正序,但是大小是否合适,就要权值线段树访问上一层并且比当前值
- 大的数的和,树状数组也可以实现,转移方程为:
-
dp[i][j]=(query(n)-query(s[j])+mod)%mod
-
#include<bits/stdc++.h> using namespace std; #define ll long long #define mod 1000000000 #define maxn 234567 ll tree[maxn],ans; int s[maxn],n,k; ll dp[15][maxn],lhk; int inline lowbit(int x) { return x&(-x); } void updata(int x,ll d) { while(x<=n) { tree[x]+=d; x+=lowbit(x); } } ll query(int x) { ll ans=0; while(x>0) { ans+=tree[x]; ans%=mod; x-=lowbit(x); } return ans; } int main() { scanf("%d%d",&n,&k); for(int i=1; i<=n; i++) { scanf("%d",&s[i]); dp[1][i]=1; } for(int i=2; i<=k; i++) { memset(tree,0,sizeof(tree)); for(int j=1; j<=n; j++) { updata(s[j],dp[i-1][j]); dp[i][j]=(query(n)-query(s[j])+mod)%mod; if(i==k) lhk=(lhk+dp[k][j])%mod; } } printf("%lld\n",lhk); return 0; }
C - K-inversions URAL - 1523 -dp-权值树
最新推荐文章于 2021-05-29 11:27:22 发布