MIS
来源:互联网 发布:网络高清图片 编辑:程序博客网 时间:2024/04/29 06:18
题目描述 长度为m的递增子序列(M length IncreaseSubsequence),称为MIS。
求长度为n的序列,有多少个MIS。子序列不需要在原序列中不需要连续,但要保证相对位置。 输入
第一行两个整数n和m第二行n个整数,表示一个序列。 输出 输出MIS的个数,结果对20140921取余。
对于100%的数据,n的范围[1,10000],m的的范围[1,100],序列中的元素范围[1,109];
题目分析: 关键字:DP,线段树优化(dp离散线段树) 首先,可以由本题想到LIS,从而想到DP,给出三要素
定义:dp[i][j]表示以i为结尾前面达到长度为j时拥有的方案数
初始化:for i to n dp[i][1]=1;
状态转移方程:dp[i][j]={∑dp[k][j-1] | k < i && A[k] < A[i]}
暴力: for(int i=1;i<=n;i++) dp[i][1]=1;for(int i=1;i<=n;i++) for(int j=2;j<=m;j++) for(int k=i-1;k>=1;k--) if(A[k]<A[i]) dp[i][j]+=dp[k][j-1];
优化:观察,发现对于每一对(i,j)而言,就是把所有下标小于i,权值小于自己的dp[k][j-1]相加
若是权值有了单调性,那么第一个权值满足后,之后所有的都满足,区间查询,就可以想到线段树了。剩下就是下标的问题,但这其实是不需要考虑的,因为我们建了一颗权值线段树后,初始值是0,而下标小的一定先被更新到,那么下标大的就不会对其产生影响,每次查询之后修改,就一定能保证跟新次序是对的(注意一些小细节,就可以了);最后题目复杂度为O(n*m*log(n));
注:代码实现能力是练出来的,一定要敲一遍
WA:
1. 线段树中update中把x当成了pos用(变量混用)
2. 以i为结尾长度为1的个数显然为1,所以自己直接更新在线段树上,dp值没更新(注意关联变量之间的互相更新。
#include<bits/stdc++.h>using namespace std;#define N 10005#define M 105#define MOD 20140921#define FOR(i,a,b) for(int i=(a);i<=(b);i++)#define DOR(i,a,b) for(int i=(a);i>=(b);i--)int A[N],dp[N][M],T[N],tmp[N];int n,m,ans;void add(int &a,int b){ a+=b%MOD; if(a>=MOD) a-=MOD;}struct Segment{ struct{ int L,R,sum; }tree[N<<2]; void Up(int p){tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%MOD;} void build(int p,int L,int R){ tree[p].L=L,tree[p].R=R; if(L==R){ tree[p].sum=0; return; } int mid=(L+R)>>1; build(p<<1,L,mid); build(p<<1|1,mid+1,R); Up(p); } int query(int p,int L,int R){ if(tree[p].L==L&&tree[p].R==R){ return tree[p].sum; } int mid=(tree[p].L+tree[p].R)>>1; if(R<=mid) return query(p<<1,L,R)%MOD; else if(L>mid) return query(p<<1|1,L,R)%MOD; else return (query(p<<1,L,mid)+query(p<<1|1,mid+1,R))%MOD; } void update(int p,int pos,int x){ if(tree[p].L==tree[p].R){ add(tree[p].sum,x); return; } int mid=(tree[p].L+tree[p].R)>>1; if(pos<=mid) update(p<<1,pos,x); else update(p<<1|1,pos,x); Up(p); }}tree[M];int main(){ scanf("%d %d",&n,&m); FOR(i,1,n) scanf("%d",&A[i]),tmp[i]=A[i]; sort(tmp+1,tmp+1+n); int tmp_len=unique(tmp+1,tmp+1+n)-tmp-1; FOR(i,1,m) tree[i].build(1,1,tmp_len); FOR(i,1,n){ int pos=lower_bound(tmp+1,tmp+tmp_len+1,A[i])-tmp; tree[1].update(1,pos,1); dp[i][1]=1; if(pos>1) FOR(j,2,m){ dp[i][j]=tree[j-1].query(1,1,pos-1)%MOD; tree[j].update(1,pos,dp[i][j]); } } FOR(i,1,n) add(ans,dp[i][m]); printf("%d\n",ans%MOD); return 0;}
- MIS
- MIS
- MIS
- MIS
- MIS
- MIS
- MIS
- MIS
- MIS
- ERP,MIS
- 什么是MIS?
- 什么是MIS?
- MIS简介
- MIS系统
- mis系统
- JAVA-MIS
- QQ2010.mis
- MIS管理信息系统
- 成年人的世界里,没有男女两个字
- jq代码学习10--文本框高度变化(内容滚动)
- spring.profiles.active=dev
- jq学习代码11-----复选框全选反选
- < 笔记 > Python
- MIS
- elasticsearch分布式集群搭建
- 【CodeForces】 670D1
- Centos使用 upzip 命令
- jq代码学习12---下拉框左右选择
- 做老板后才明白,这4种打工思维会慢慢毁掉你的未来
- BZOJ 2244 拦截导弹 cdq分治
- Ubuntu14.04 NVIDIA显卡驱动安装 + Cuda7.5 + cudnn6.0
- android开发-IntentService的原理(非主线程创建Handler的情况)