手动博客搬家: 本文发表于20170821 14:32:05, 原地址https://blog.csdn.net/suncongbo/article/details/77449455

URL: (Luogu) https://www.luogu.org/problem/show?pid=1198, (BZOJ)http://www.lydsy.com/JudgeOnline/problem.php?id=1012

题目大意:

给定一个数列,开始为空。维护两种操作:

(1) Q L表示查询当前数列后L个数的最大值。

(2) A N表示在当前数列末尾添加一个新数,这个新数的值等于上一次Q操作的答案加上给定的参数N. 若之前未进行Q操作,则添加的数为N.

思路分析:

此题牵扯到区间最值,我们可以用线段树进行解决。

但是Q操作由于需要插入元素,所以我们需要将其转化为能够利用线段树解决的问题。

这个序列是动态的,我们不妨将它变成静态的。

模拟添数的过程,对于每次查询,存下每次查询的区间左右端点,对于每次插入,记下插入的数以及它所对应的前一次查询的编号,便于后面找到上一次查询的答案。

然后,对记下的插入的数字先建线段树。

最后,循环枚举每次询问,在询问中继续枚举它所对应的插入,更新每次插入的值,以线段树单点修改的功能来实现。

看似先枚举询问,再枚举插入,是两重循环,但是由于在此循环中枚举插入的j只增不减(详见代码),因此不会超时。

部分易错点:

注意第0次询问(即前面没有询问)的情况要单列。

代码呈现:

(Luogu: Time: 712 MS; Memory: 12.05 MB; Code: 2.04 KB)

(BZOJ: Time: 1088 MS; Memory: 13324 KB; Code: 2333 B)

注: 由于不同OJ评测方式不尽相同,因此时间空间等结果有所差别,属正常现象

  1. ​#include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int MAXN = 2e5;
  5. int MODN;
  6. struct Node
  7. {
  8. int left,right;
  9. int maxi;
  10. };
  11. struct SegmentTree
  12. {
  13. Node nd[MAXN*4+2];
  14. void init()
  15. {
  16. for(int i=1; i<=MAXN*4; i++)
  17. {
  18. nd[i].left = nd[i].right = nd[i].maxi = 0;
  19. }
  20. }
  21. void build(int lbound,int rbound,int pos,int a[])
  22. {
  23. nd[pos].left = lbound;
  24. nd[pos].right = rbound;
  25. if(lbound==rbound)
  26. {
  27. nd[pos].maxi = a[lbound];
  28. return;
  29. }
  30. int mid = (lbound+rbound)/2;
  31. build(lbound,mid,2*pos,a);
  32. build(mid+1,rbound,2*pos+1,a);
  33. nd[pos].maxi = max(nd[2*pos].maxi,nd[2*pos+1].maxi);
  34. }
  35. void modify(int bound,int val,int pos)
  36. {
  37. int mid = (nd[pos].left+nd[pos].right)/2;
  38. if(nd[pos].left==nd[pos].right)
  39. {
  40. nd[pos].maxi = val;
  41. return;
  42. }
  43. if(bound<=mid) modify(bound,val,2*pos);
  44. else modify(bound,val,2*pos+1);
  45. nd[pos].maxi = max(nd[2*pos].maxi,nd[2*pos+1].maxi);
  46. }
  47. int query(int lbound,int rbound,int pos)
  48. {
  49. int mid = (nd[pos].left+nd[pos].right)/2;
  50. if(lbound==nd[pos].left && rbound==nd[pos].right) return nd[pos].maxi;
  51. int ans;
  52. if(rbound<=mid) ans = query(lbound,rbound,2*pos);
  53. else if(lbound>mid) ans = query(lbound,rbound,2*pos+1);
  54. else ans = max(query(lbound,mid,2*pos),query(mid+1,rbound,2*pos+1));
  55. return ans;
  56. }
  57. };
  58. SegmentTree st;
  59. int a[MAXN+2];
  60. int p[MAXN+2];
  61. int ql[MAXN+2];
  62. int qr[MAXN+2];
  63. int n,m,q;
  64. int main()
  65. {
  66. char ch[5];
  67. int x;
  68. n = q = 0;
  69. scanf("%d%d",&m,&MODN);
  70. for(int i=1; i<=m; i++)
  71. {
  72. scanf("%s",ch);
  73. switch(ch[0])
  74. {
  75. case 'A':
  76. {
  77. scanf("%d",&x);
  78. a[++n] = x;
  79. p[n] = q;
  80. break;
  81. }
  82. case 'Q':
  83. {
  84. scanf("%d",&x);
  85. ql[++q] = n-x+1;
  86. qr[q] = n;
  87. break;
  88. }
  89. }
  90. }
  91. st.init();
  92. st.build(1,n,1,a);
  93. int j = 1;
  94. while(j<=n && !p[j])
  95. {
  96. j++;
  97. }
  98. for(int i=1; i<=q; i++)
  99. {
  100. int ans = st.query(ql[i],qr[i],1);
  101. printf("%d\n",ans);
  102. while(j<=n && p[j]==i)
  103. {
  104. st.modify(j,(int)((long long)a[j]+ans)%MODN,1);
  105. j++;
  106. }
  107. }
  108. return 0;
  109. }​

Luogu P1198 BZOJ 1012 最大数 (线段树)的更多相关文章

  1. bzoj 1012 基础线段树

    原题传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1012 今儿一天状态不好,都没怎么刷题..快下课了,刷道水题.... 裸的线段树 /*** ...

  2. BZOJ 1012【线段树】

    题意: Q L 询问数列最后 L 个数中最大的数. A n 将 n + t ( t_init = 0 ), 然后插到最后去. 思路: 感觉动态地插入,很有问题. 数组地长度会时常变化,但是可以先预处理 ...

  3. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  4. luogu P2574 XOR的艺术 (线段树)

    luogu P2574 XOR的艺术 (线段树) 算是比较简单的线段树. 当区间修改时.\(1 xor 1 = 0,0 xor 1 = 1\)所以就是区间元素个数减去以前的\(1\)的个数就是现在\( ...

  5. 【原创】洛谷 LUOGU P3373 【模板】线段树2

    P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格式: 第 ...

  6. 【原创】洛谷 LUOGU P3372 【模板】线段树1

    P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别 ...

  7. [BZOJ 4025]二分图(线段树分治+带边权并查集)

    [BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...

  8. BZOJ 1012 最大数maxnumber 线段树

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1012 题目大意: 见链接 思路: 直接用线段树模拟一下就可以了. #include&l ...

  9. 洛谷 - P1198 - 最大数 - 线段树

    https://www.luogu.org/problemnew/show/P1198 要问区间最大值,肯定是要用线段树的,不能用树状数组.(因为没有逆元?但是题目求的是最后一段,可以改成类似前缀和啊 ...

随机推荐

  1. SQL server触发器、存储过程操作远程数据库插入数据,解决服务器已存在的问题

    近期弄了一个小项目,也不是非常复杂,须要将一个数据库的一些数据备份到另外一个库.不是本地,可能是网络上其它的数据库.想了一下,用了存储过程和触发器. 也不是非常复杂,首先我须要操作远程数据库,于是写了 ...

  2. QFileDialog关于选择文件对话框中的几个信号的说明(currentChanged,directoryEntered,fileSelected,filterSelected)

    QFileDialog关于选择文件对话框中的几个信号 实例: openFile::openFile(QWidget *parent) :QWidget(parent),ui(new Ui::openF ...

  3. C++ Development Library

    C/C++ 开发库 | C/C++ Development Library 这里收集一些著名的 C/C++ 开发库.SDK.类库.可复用类与结构代码 等信息,列举它们的介绍.参考和网站链接,为各位 C ...

  4. KNN in c++

    Pseudo Code of KNN We can implement a KNN model by following the below steps: Load the data Initiali ...

  5. 把一个文件夹下的多个csv文件合并到一个excel的多个sheet

    #!/usr/bin/env python3 # -*- coding: UTF-8 -*- import pandas as pd import os import re if __name__ = ...

  6. python关于文件的操作

    总是记不住API.昨晚写的时候用到了这些,但是没记住,于是就索性整理一下吧: python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Pyth ...

  7. javascript--给你的JS代码添加单元测试

    通过测试框架为JavaScript应用添加测试,从而保证代码的高质量.这里的笔记例子应用在jaywcjlove/validator.js中. 安装 用到三个工具chai(断言工具),mocha(测试框 ...

  8. java web支持jsonp跨域

    jsonp跨域请求处理 Jsonp(JSON with Padding) 是 json的一种"使用模式",可以让网页从别的域名(网站)那获取资料,绕过同源策略(若地址里面的协议.域 ...

  9. nodejs windows环境安装

    相信对于很多关注javascript发展的同学来说,nodejs已经不是一个陌生的词眼.有关nodejs的相关资料网上已经铺天盖地.由于它的高并发特性,造就了其特殊的应用地位. 国内目前关注最高,维护 ...

  10. nodejs express开发

    用NodeJS+Express开发WEB应用---第一篇 大漠穷秋2014-03-28 预热 为了对后面的内容理解更加透彻,推荐首先阅读下面这篇很好的文章: http://www.nodebeginn ...