Description

小A有N个正整数,紧接着,他打算依次在黑板上写下这N个数。对于每一个数,他可以决定将这个数写在当前数列的最左边或最右边。现在他想知道,他写下的数列的可能的最长严格上升子序列(可由不连续的元素组成)的长度是多少,同时他还想知道有多少种不同的最长的严格上升子序列。
两个子序列被认为是不同的当且仅当:两个子序列属于两个不同的写序列方案(两个写序列方案中有至少一步是不一样的)或两个子序列位于同一写序列方案的不同位置。
由于结果可能很大,所以小A只需要知道最长严格上升子序列的方案数对10^9+7取模的结果。

 

Input

第一行一个正整数N(1<=N<=2*10^5)。
第二行包含N个由空格隔开的正整数,表示小A写下的初始序列。序列中的每一个元素小于等于10^9。

Output

输出包含一行,输出最长严格上升子序列的长度以及方案数对10^9+7取模的结果。

 

Sample Input

  1. 输入1
  2. 2
  3. 1 1
  4. 输入2
  5. 4
  6. 2 1 3 4

Sample Output

  1. 输出1
  2. 1 4
  3. 输出2
  4. 4 1
 

Data Constraint

30%的数据满足:N<=20
50%的数据满足:N<=1000

Solution

题目有一个隐藏性质是这样的

答案的第一问是对于每个点为结束点或开始点求出的最长上升序列长度和最长下降序列长度之和

在dp以上两个值的过程中同时统计方案数,用树状数组可以n log n时间复杂度做到

  1. #include <vector>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <algorithm>
  5. #define set_file(File) freopen(#File".in", "r", stdin), freopen(#File".out", "w", stdout)
  6. #define close_file() fclose(stdin), fclose(stdout)
  7. #define ll long long
  8. #define mo 1000000007
  9. #define maxn 200010
  10.  
  11. template<class T> inline void Rin(T &x)
  12. {
  13. int c = getchar();
  14. for(x = 0; c < 48 || c > 57; c = getchar());
  15. for(; c > 47 && c < 58; c = getchar()) x = (x << 1) + (x << 3) + c - 48;
  16. }
  17.  
  18. std::vector<int> VeH;
  19.  
  20. int n, seq[maxn], mx[maxn], c[maxn], f[maxn], fs[maxn], g[maxn], gs[maxn];
  21.  
  22. void get_ans_lef(int i)
  23. {
  24. int x = seq[i] - 1, tot = 1, ans = 0;
  25. for(; x; x -= x & -x)
  26. {
  27. if(mx[x] > ans) ans = mx[x], tot = c[x];
  28. else if(mx[x] == ans) tot = (tot + c[x]) % mo;
  29. }
  30. f[i] = ans + 1, fs[i] = tot;
  31. x = seq[i];
  32. for(; x <= n; x += x & -x)
  33. {
  34. if(mx[x] < f[i]) mx[x] = f[i], c[x] = fs[i];
  35. else if(mx[x] == f[i]) c[x] = (c[x] + fs[i]) % mo;
  36. }
  37. }
  38.  
  39. void get_ans_rig(int i)
  40. {
  41. int x = seq[i] - 1, tot = 1, ans = 0;
  42. for(; x; x -= x & -x)
  43. {
  44. if(mx[x] > ans) ans = mx[x], tot = c[x];
  45. else if(mx[x] == ans) tot = (tot + c[x]) % mo;
  46. }
  47. g[i] = ans + 1, gs[i] = tot;
  48. x = seq[i];
  49. for(; x <= n; x += x & -x)
  50. {
  51. if(mx[x] < g[i]) mx[x] = g[i], c[x] = gs[i];
  52. else if(mx[x] == g[i]) c[x] = (c[x] + gs[i]) % mo;
  53. }
  54. }
  55.  
  56. int main()
  57. {
  58. set_file(sequence);
  59. Rin(n);
  60. for(int i = n; i; i--)
  61. {
  62. Rin(seq[i]);
  63. VeH.push_back(seq[i]);
  64. }
  65. std::sort(VeH.begin(), VeH.end());
  66. VeH.erase(unique(VeH.begin(), VeH.end()), VeH.end());
  67. for(int i = 1; i <= n; i++) seq[i] = std::lower_bound(VeH.begin(), VeH.end(), seq[i]) - VeH.begin() + 1;
  68. for(int i = 1; i <= n; i++) get_ans_lef(i);
  69. memset(mx, 0, sizeof mx);
  70. memset(c, 0, sizeof c);
  71. for(int i = 1; i <= n; i++) seq[i] = n - seq[i] + 1;
  72. for(int i = 1; i <= n; i++) get_ans_rig(i);
  73. int tot = 0, ans = 0;
  74. for(int i = 1; i <= n; i++)
  75. if(f[i] + g[i] - 1 > ans) ans = f[i] + g[i] - 1, tot = (ll)fs[i] * gs[i] % mo;
  76. else if(f[i] + g[i] - 1 == ans) tot = (tot + (ll)fs[i] * gs[i] % mo) % mo;
  77. for(int i = 1; i <= n - ans; i++) tot = (ll)tot * 2 % mo;
  78. printf("%d %d\n", ans, tot);
  79. close_file();
  80. return 0;
  81. }

  

NOI模拟赛(3.15) sequence(序列)的更多相关文章

  1. Java 第十一届 蓝桥杯 省模拟赛 正整数的摆动序列

    正整数的摆动序列 问题描述 如果一个序列的奇数项都比前一项大,偶数项都比前一项小,则称为一个摆动序列.即 a[2i]<a[2i-1], a[2i+1]>a[2i]. 小明想知道,长度为 m ...

  2. 6.28 NOI模拟赛 好题 状压dp 随机化

    算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...

  3. NOI模拟赛 Day1

    [考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...

  4. NOI.ac模拟赛20181021 ball sequence color

    T1 ball 可以发现每次推动球时,是将每个球的位置 −1-1−1 ,然后把最左边的球放到 P−1P-1P−1 处. 记个 −1-1−1 次数,再用set维护就好了. #include <bi ...

  5. NOI 模拟赛 #2

    得分非常惨惨,半个小时写的纯暴力 70 分竟然拿了 rank 1... 如果 OYJason 和 wxjor 在可能会被爆踩吧 嘤 T1 欧拉子图 给一个无向图,如果一个边集的导出子图是一个欧拉回路, ...

  6. 【NOI模拟赛(湖南)】DeepDarkFantasy

    DeepDarkFantasy 从东京出发,不久便到一处驿站,写道:日暮里.  ——鲁迅<藤野先生> 定义一个置换的平方为对1~n的序列做两次该置换得到的序列.已知一个置换的平方,并且这个 ...

  7. [模拟赛] T3 最优序列

    Description 给出一个长度为n(n<=1000)的正整数序列,求一个子序列,使得原序列中任意长度为m的子串中被选出的元素不超过k(k<=m<=10)个,并且选出的元素之和最 ...

  8. NOI模拟赛 #4

    好像只有一个串串题可以做... 不会 dp 和数据结构啊 QAQ 10 + 20 + 100 = 130 T1 一棵树,每个点有一个能量的最大容量 $l_i$ 和一个增长速度 $v_i$,每次可以选一 ...

  9. NOI 模拟赛 #3

    打开题一看,咦,两道数数,一道猫式树题 感觉树题不可做呀,暴力走人 数数题数哪个呢?感觉置换比矩阵好一些 于是数了数第一题 100 + 0 + 15 = 115 T1 bishop 给若干个环,这些环 ...

随机推荐

  1. net 上传视频

    [HttpPost]        public ActionResult MultiUpload()        {            System.Web.HttpFileCollectio ...

  2. 把AM_B_ENTRY表里的ARCHIVAL_CODE字段,值复制给BA_ARCHIVAL_CODE_160812字段

    UPDATE AM_B_ENTRY T SET T.BA_ARCHIVAL_CODE_160812=T.ARCHIVAL_CODE SELECT BA_ARCHIVAL_CODE_160812 FRO ...

  3. E. Anton and Tree 数组开大点

    http://codeforces.com/contest/734/problem/E 看了题解,缩点 + 树的直径. 然而一直wa14. 注意到, 缩点后重建图,在5的时候,5和6建了一条边,然后6 ...

  4. mysql 三大范式【转载】

    第一范式(1NF,normal format):字段不能再分. 这是字段的原子性.例如:字段“学期时间”:2014-9-1,2015-1-15. 这个字段“学期时间”可以再分为“学期开始时间”,201 ...

  5. 设计模式(3)-- 原型模式 (clone分析)

    原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建对象. 在java中有语言级别的支持:clone 在java中使用原型模式是非常简单的事情,实现Cloneable接口,调用Objec ...

  6. iOS开发中的HTML解析

    在进行解析前,先将下面的第三方类添加到工程中: 添加以上三个类必须添加一个库,这个库是:libxml2.2.dylib. 还需要设置一些路径参数这个路径的设置,在 targets中,在build se ...

  7. ubuntu下php安装目录说明

    php当前安装目录 /etc/php5/ apache2:   采用APACHE2HANDLER启动 cli:   采用命令启动 fpm php-fpm启动 fpm2     php-fpm多实例 m ...

  8. Git理论知识补充

    转自: http://www.cnblogs.com/hnrainll/archive/2012/11/13/2768003.html 对于任何一个文件,在 Git 内都只有三种状态:已提交(comm ...

  9. CAD交互绘制直线(网页版)

    用户可以在CAD控件视区任意位置绘制直线. 主要用到函数说明: _DMxDrawX::DrawLine 绘制一个直线.详细说明如下: 参数 说明 DOUBLE dX1 直线的开始点x坐标 DOUBLE ...

  10. atoi (String to Integer) leetcode

    将字符串转化为数字,其注意事项有: Requirements for atoi: The function first discards as many whitespace characters a ...