当时比赛时超时了,那时没学过树状数组,也不知道啥叫离散化(貌似好像现在也不懂)。百度百科——离散化,把无限空间中无限的个体映射到有限的空间中去,以此提高算法的时空效率。

这道题是dp题,离散化和树状数组用来优化,状态转移方程:dp[i][j]=sum(dp[i-1][k])----k需要满足a[j]>a[k]&&k<j;

i表示所要选的个数,j表示以第a[j]个数结尾所有的符合要求的递增串的个数,最后答案就是sum(dp[n][j])--1<=j<=p;n 为要选的个数,p为所给数的总数,这个方程很容易想,这里不说了

(因为叫我说也说不清)。

数据肯定很大所以题目要求取模。

今天刚学树状数组还不太会用。

下面给出树状数组的模板

 1 int bit[MAX_N+1],n;
2 int sum(int i)
3 {
4 int s=0;
5 while(i>0)
6 {
7 s+=bit[i];
8 i-=i&-i;
9 }
10 return s;
11 }
12
13
14 void add(int i,int x)
15 {
16 while(i<=n)
17 {
18 bit[i]+=x;
19 i+=i&-i;
20 }
21 }

为什么要离散化呢,因为N的范围为1000,而所给元素a[i]的范围为1e+9;

用树状数组时开不了那么大的数组,所以要离散化,将所给的数对应到1000以内连续的数,这样不会改变每个数之间的大小关系。

那么树状数组就可以开bit[1005];最后复杂度为n2log(n);

下面给出代码

 1 #include<stdio.h>
2 #include<algorithm>
3 #include<string.h>
4 #include<stdlib.h>
5 #include<iostream>
6 #include<map>
7 typedef long long ll;
8 ll sum(int n);
9 void add(int n,ll kk,int z);
10 ll dp[1005][1005];
11 int a[1005];
12 int b[1005];
13 int bit[1005];//树状数组
14 const ll pp=1e9+7;
15 using namespace std;
16 int main(void)
17 {
18 int n,i,j,k,p,q;
19 scanf("%d",&n);
20 for(i=1; i<=n; i++)
21 {
22 map<int,int>my;//用来离散化的(将大的数转化1000以内的数)
23 memset(dp,0,sizeof(dp));
24 for(j=0; j<=1000; j++)
25 {
26 dp[1][j]=1;
27 }//当就选1个时全初始化1
28 scanf("%d %d",&p,&q);
29 for(j=1; j<=p; j++)
30 {
31 scanf("%d",&a[j]);
32 b[j]=a[j];
33 }
34 sort(b+1,b+p+1);//离散化前的排序比如200 300 100 排完为100 200 300 那么对应为1 2 3
35 int c[1005];
36 int cnt=1;
37 for(j=1; j<=p; j++)
38 {
39 if(j==1)
40 {
41 my[b[j]]=cnt;
42 }
43 else
44 {
45 if(b[j]!=b[j-1])
46 {
47 cnt++;
48 my[b[j]]=cnt;
49 }
50 else
51 {
52 my[b[j]]=cnt;
53 }
54 }
55 }
56 for(j=1; j<=p; j++)
57 {
58 a[j]=my[a[j]];
59 }//将原数组每个元素改为对应元素 200 100 300 -〉2 1 3
60 for(j=2; j<=q; j++)//要选的个数
61 {
62 memset(bit,0,sizeof(bit));
63 for(k=j-1; k<=p; k++)//可以改成从1循不过时间长
64 {
65 ll nn=sum(a[k]-1);
66 dp[j][k]=nn;
67 add(a[k],dp[j-1][k],cnt);
68 }
69 }
70 ll endd=0;
71 for(j=1; j<=p; j++)
72 {
73 endd=(endd+dp[q][j])%pp;
74 }
75 printf("Case #%d: ",i);
76 printf("%lld\n",endd);
77 }
78 return 0;
79 }
80 ll sum(int n)
81 {
82 ll s=0;
83 while(n>0)
84 {
85 s=(bit[n]+s)%pp;
86 n=n&(n-1);
87 }
88 return s;
89 }
90 void add(int n,ll kk,int z)
91 {
92 while(n<=z)
93 {
94 bit[n]=(kk+bit[n])%pp;
95 n+=(n&(-n));
96 }
97 }

最新文章

  1. React Native知识5-Touchable类组件
  2. redis 相关命令
  3. Ext1.X的CheckboxSelectionModel默认全选之后不允许编辑的BUG解决方案
  4. unity 解析tmx
  5. Winform开发框架之单据窗体生成(主从表,流水单号)
  6. HDU 1521 排列组合 指数型母函数
  7. AJAX安全-Session做Token
  8. easyui 获取cloumns字段
  9. 一步一步学数据结构之1--n(通用树)
  10. typedef和define具体的具体差别
  11. 在Window和Linux下使用Zthread库
  12. LeetCode_Merge Two Sorted Lists
  13. 如何优雅的研究 RGSS3 (七) 加入LOGO屏幕
  14. HihoCoder
  15. 关于javascript代码优化的8点建议
  16. # electron-vue 尝试做个网易云音乐
  17. Logstash安装介绍
  18. 【ARTS】01_10_左耳听风-20190114~20190120
  19. 学习-HTML5
  20. java 方法的返回类型

热门文章

  1. js获取中国省市区,省市筛选、省市、省市筛选联动。【C#】【js】
  2. C语言中的各种字符串输入方法
  3. 19. 删除链表的倒数第 N 个结点
  4. 日常Java 2021/11/3
  5. accommodate, accompany
  6. 编程之美Q1
  7. jenkins的sonarqube之代码检测的两种方法
  8. spring注解-组件注册
  9. Linux基础命令---nfsstat显示nfs信息
  10. 【JAVA】【Basic】概念