1012: [JSOI2008]最大数maxnumber

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 9851  Solved: 4318
[Submit][Status][Discuss]

Description

  现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。

Input

  第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。

Output

  对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。

Sample Input

5 100
A 96
Q 1
A 97
Q 1
Q 2

Sample Output

96
93
96

HINT

  数据如下http://pan.baidu.com/s/1i4JxCH3

Source

线段树

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. #define L(root) ((root) << 1)
  5. #define R(root) (((root) << 1) | 1)
  6.  
  7. const int MAXN = + ;
  8. int numbers[MAXN];
  9.  
  10. struct Node {
  11. int left, right;
  12. //int sum;//
  13. int mx;//最大值
  14. int mid()
  15. {
  16. return left + ((right - left) >> );
  17. }
  18. } tree[MAXN * ];
  19.  
  20. void pushUp(int root)
  21. {
  22. // tree[root].sum = tree[L(root)].sum + tree[R(root)].sum;
  23. tree[root].mx = max(tree[L(root)].mx, tree[R(root)].mx);
  24. }
  25.  
  26. void build(int root, int left, int right)
  27. {
  28. tree[root].left = left;
  29. tree[root].right = right;
  30. if (left == right) {
  31. // tree[root].sum = numbers[left];
  32. tree[root].mx = ;
  33. return;
  34. }
  35. int mid = tree[root].mid();
  36. build(L(root), left, mid);
  37. build(R(root), mid + , right);
  38. pushUp(root);
  39. }
  40.  
  41. int query(int root, int left, int right)
  42. {
  43. if (tree[root].left == left && tree[root].right == right) {
  44. // return tree[root].sum;
  45. return tree[root].mx;
  46. }
  47. int mid = tree[root].mid();
  48. if (right <= mid) {
  49. return query(L(root), left, right);
  50. } else if (left > mid) {
  51. return query(R(root), left, right);
  52. } else {
  53. //return query(L(root), left, mid) + query(R(root), mid + 1, right);
  54. //注意返回最大值...
  55. int lv = query(L(root), left, mid);
  56. int rv = query(R(root), mid + , right);
  57. return lv > rv ? lv : rv;
  58. }
  59. }
  60.  
  61. void update(int root, int pos, int add)
  62. {
  63. if (tree[root].left == tree[root].right) {
  64. //tree[root].sum = tree[root].sum + add;
  65. tree[root].mx = add;
  66. return;
  67. }
  68. int mid = tree[root].mid();
  69. if (pos <= mid) {
  70. update(L(root), pos, add);
  71. } else {
  72. update(R(root), pos, add);
  73. }
  74. pushUp(root);
  75. }
  76.  
  77. void test01()
  78. {
  79. memset(numbers, , sizeof(numbers));
  80. int i;
  81. for (i = ; i < MAXN; ++i) {
  82. numbers[i] = i;
  83. }
  84. build(, , );
  85. printf("%d\n", query(, , ));
  86. update(, , );
  87. printf("%d\n", query(, , ));
  88. }
  89.  
  90. int main()
  91. {
  92. //test01();
  93.  
  94. int M, D;
  95. char str[];
  96. int x;
  97. int i;
  98. int t;
  99. int len;//当前长度
  100.  
  101. while (~scanf("%d%d", &M, &D)) {
  102. build(, , M);
  103.  
  104. t = ;
  105. len = ;
  106. for (i = ; i < M; ++i) {
  107. scanf("%1s%d", str, &x);
  108. if (str[] == 'Q') {
  109. t = query(, len - x + , len);
  110. printf("%d\n", t);
  111. } else {
  112. update(, ++len, (x + t) % D);
  113. }
  114. }
  115. }
  116.  
  117. return ;
  118. }

树状数组(代码好难理解,日后再看)

  1. 区间最值其实和区间求和差不多,就是将sum数组的含义转移到max,然后通过特定的区间更新max
  2.  
  3. 在区间求和中,当我们维护max[i]的时候,要找到它前面所有的max[j]来更新,在这里因为是树状数组,所以可以降成一个log级,画图可知,max[i]需要的max只有max[i-^],max[i-^],max[i-^]..max[i-lowbit(i)+]
  4.  
  5. 更新操作简单,即
  6.  
  7. void change(int r) {
  8. c[r]=num[r];
  9. for(int i=; i<lowbit(r); i<<=)
  10. c[r]=max(c[r], c[r-i]);
  11. }
  12. 接下来是求区间最值,很容易看出,我们找[l,r]的最值就是找在次区间的max,即递减r,在这里可以有个优化,即当找到一个max[i],有i-lowbit(i)>=l时,更新后,i直接-=lowbit(i),然后继续递减。当l>=r就跳出循环
  13.  
  14. int getk(int l, int r) {
  15. int ret=num[r];
  16. while(l<=r) {
  17. ret=max(ret, num[r]);
  18. for(--r; r-l>=lowbit(r); r-=lowbit(r))
  19. ret=max(ret, c[r]);
  20. }
  21. return ret;
  22. }
  23. 其实在这里更新操作可以和区间最值放在一起,(现在用c代表max)即c[i]=max(getk(i-lowbit(i)+, i), num[i]);
  1. #include <cstdio>
  2. using namespace std;
  3. #define lowbit(x) (x&-x)
  4. #define max(a,b) ((a)>(b)?(a):(b))
  5. const int N=;
  6. int num[N], c[N], cnt;
  7. int getk(int l, int r) {
  8. int ret=num[r];
  9. while(l<=r) {
  10. ret=max(ret, num[r]);
  11. for(--r; r-l>=lowbit(r); r-=lowbit(r))
  12. ret=max(ret, c[r]);
  13. }
  14. return ret;
  15. }
  16.  
  17. int main() {
  18. int n, d, t=, a;
  19. char ch[];
  20. scanf("%d%d", &n, &d);
  21. while(n--) {
  22. scanf("%s%d", ch, &a);
  23. if(ch[]=='A') {
  24. num[++cnt]=(t+a)%d;
  25. c[cnt]=max(getk(cnt-lowbit(cnt)+, cnt-), num[cnt]);
  26. }
  27. else {
  28. printf("%d\n", t=getk(cnt-a+, cnt));
  29. }
  30. }
  31. return ;
  32. }

单调递减队列/ 单调递增栈

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <climits>
  7. #define N 1000000
  8. #define INF INT_MAX
  9.  
  10. using namespace std;
  11.  
  12. //单调递减队列, [队首, 队尾], [3, 2, 1], 队列中存下标
  13. //单调递增栈, [栈底, 栈顶], [3, 2, 1]
  14. int q[N],m,d,h=,t=,num;
  15. int val[N],ans;
  16.  
  17. //二分找到x后面第一个数
  18. inline int getans(int x)
  19. {
  20. int l=h,r=t-,mid,res;
  21. while(l<=r)
  22. {
  23. mid=(l+r)>>;
  24. if(x<=q[mid]) res=mid,r=mid-;
  25. else l=mid+;
  26. }
  27. return q[res];
  28. }
  29.  
  30. inline void go()
  31. {
  32. scanf("%d%d",&m,&d);
  33. int a;
  34. char str[];
  35. while(m--)
  36. {
  37. scanf("%s%d",str,&a);
  38. if(str[]=='A')
  39. {
  40. val[++num]=(a+ans)%d;
  41. while(h<t&&val[q[t-]]<=val[num]) t--;
  42. q[t++]=num;
  43. }
  44. else
  45. {
  46. //二分
  47. ans=val[getans(num-a+)];
  48. printf("%d\n",ans);
  49. }
  50. }
  51. }
  52.  
  53. int main()
  54. {
  55. go();
  56. return ;
  57. }

下面的代码比较挫了,如果输入序列递增,估计要超时。辅助理解单调队列思想。

  1. //qscqesze
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <ctime>
  6. #include <iostream>
  7. #include <algorithm>
  8. #include <set>
  9. #include <vector>
  10. #include <sstream>
  11. #include <queue>
  12. #include <typeinfo>
  13. #include <fstream>
  14. #include <map>
  15. typedef long long ll;
  16. using namespace std;
  17. //freopen("D.in","r",stdin);
  18. //freopen("D.out","w",stdout);
  19. #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
  20. #define maxn 250001
  21. #define eps 1e-9
  22. const int inf=0x7fffffff; //无限大
  23. //**************************************************************************************
  24. int a[maxn],max_num[maxn],t=,ans=;
  25. int main()
  26. {
  27. int n,d;
  28. scanf("%d%d",&n,&d);
  29. char ch[];
  30. int g;
  31. while(n--)
  32. {
  33. scanf("%s%d",ch,&g);
  34. if(ch[]=='A')
  35. {
  36. a[++t]=(ans+g)%d;
  37. for(int i=t;i;i--)
  38. {
  39. if(max_num[i]<a[t])
  40. max_num[i]=a[t];
  41. else
  42. break;
  43. }
  44. }
  45. else
  46. {
  47. ans=max_num[t-g+];
  48. printf("%d\n",ans);
  49. }
  50. }
  51. return ;
  52. }

rmq(我写的这个速度有点捉急...)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int MAXN = + ;
  5. int mx[MAXN][];
  6. int num[MAXN];
  7. int tot;
  8.  
  9. void update()
  10. {
  11. mx[tot][] = num[tot];
  12. int k1 = log2(tot);
  13. int k2;
  14. int i, j;
  15. for (j = ; j <= k1; ++j) {
  16. k2 = tot - pow(, j) + ;
  17. for (i = k2; i <= k2; ++i) {
  18. mx[i][j] = max(mx[i][j - ], mx[i + (int)pow(, j - )][j - ]);
  19. }
  20. }
  21. }
  22.  
  23. int rmq(int i, int j)
  24. {
  25. int k = log2(j - i + );
  26. return max(mx[i][k], mx[j - (int)pow(, k) + ][k]);
  27. }
  28.  
  29. int main()
  30. {
  31. int M, D;
  32. char str[];
  33. int x;
  34. int i;
  35. int t;
  36.  
  37. while (~scanf("%d%d", &M, &D)) {
  38. tot = ;
  39. t = ;
  40. for (i = ; i < M; ++i) {
  41. scanf("%1s%d", str, &x);
  42. if (str[] == 'Q') {
  43. t = rmq(tot - x + , tot);
  44. printf("%d\n", t);
  45. } else {
  46. num[++tot] = (x + t) % D;
  47. update();
  48. }
  49. }
  50. }
  51.  
  52. return ;
  53. }

大视野 1012: [JSOI2008]最大数maxnumber(线段树/ 树状数组/ 单调队列/ 单调栈/ rmq)的更多相关文章

  1. bzoj-1012 1012: [JSOI2008]最大数maxnumber(线段树)

    题目链接: 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Description 现在请求你维护一个数列,要 ...

  2. bzoj 1012: [JSOI2008]最大数maxnumber (线段树)

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 13081  Solved: 5654[Subm ...

  3. BZOJ 1012: [JSOI2008]最大数maxnumber 线段树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1012 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能: ...

  4. 1012: [JSOI2008]最大数maxnumber 线段树

    https://www.lydsy.com/JudgeOnline/problem.php?id=1012 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数 ...

  5. BZOJ 1012: [JSOI2008]最大数maxnumber【线段树单点更新求最值,单调队列,多解】

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 10374  Solved: 4535[Subm ...

  6. BZOJ 1012: [JSOI2008]最大数maxnumber 单调队列/线段树/树状数组/乱搞

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 4750  Solved: 2145[Submi ...

  7. BZOJ-1012[JSOI2008]最大数maxnumber 线段树区间最值

    这道题相对简单下面是题目: 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MB Submit: 6542 Solve ...

  8. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  9. 【BZOJ】1012: [JSOI2008]最大数maxnumber(树状数组+rmq)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1012 树状数组原来我只懂得sum和add的操作,今天才知道可以有求区间最值的操作,我学习了一下写了个 ...

随机推荐

  1. MariaDB数据库主从复制实现步骤

    一.MariaDB简介 MariaDB数据库的主从复制方案,是其自带的功能,并且主从复制并不是复制磁盘上的数据库文件,而是通过binlog日志复制到需要同步的从服务器上. MariaDB数据库支持单向 ...

  2. 中文Ubuntu里用户目录里的路径改成英文

    (附注:转载于http://www.linuxdiyf.com/linux/201105/56.html) 为了使用起来方便,装了Ubuntu中文版,自然在home文件里用户目录的"桌面&q ...

  3. java限流(一): Semaphore

    Before obtaining an item each thread must acquire a permit from the semaphore, guaranteeing that an ...

  4. HDFS权限

    1.1 超级用户 启动namenode服务的用户就是超级用户, 该用户的组是supergroup 1.2 文件权限管理   1.2.1 创建时的owner和group 文件或者目录被创建之时,服从BS ...

  5. (4.14)存储:RAID在数据库存储上的应用

    关键词:(4.14)存储:RAID在数据库存储上的应用 转自:http://blog.51cto.com/qianzhang/1251260 随着单块磁盘在数据安全.性能.容量上呈现出的局限,磁盘阵列 ...

  6. Python2 socket 多线程并发 TCPServer Demo

    #coding=utf-8 import socket import threading,getopt,sys,string opts, args = getopt.getopt(sys.argv[1 ...

  7. 2015.7.8(千股跌停!做T不应当只做中色,中国软件)

    2015.7.81.今天开盘所有的股票全部跌停,真是一大奇观! 今天中色股份和以往不同买卖盘为正! 但是中色的爬升比较慢,价位始终没有高过昨天的收盘价————这种情况下是否应该做T呢? 2.做T不应当 ...

  8. SqlHelper简单实现(通过Expression和反射)3.实体,数据传输对象(DTO)Helper类设计

    EntityHelper的主要功能有: 1.通过反射获取DTO的字段,主要提供给在需要从Entity获取数据后,填充给DTO并返回的作用: 通过反射获取PropertyInfo[]对象,然后取出Nam ...

  9. Linux Shell基础 Bash常见命令 echo命令

    概述 shell中常见的命令echo. 输出命令:echo echo命令的输出内容如果没有特殊含义,则将原内容输出到屏幕:如果输出内容有特殊含义,则输出打印其含义. 命令格式如下: [root@loc ...

  10. 【Tech】CAS RESTful API使用笔记

    在被maven,cas,tomcat各种贱人就是矫情的虐了好几天之后,终于跑通了demo,哈哈哈哈哈哈哈~ 在这里详细记录一下,给和我一样连maven都不会的小白一点福利,同时欢迎大神指正. 首先上最 ...