Luogu P1198 BZOJ 1012 最大数 (线段树)
手动博客搬家: 本文发表于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评测方式不尽相同,因此时间空间等结果有所差别,属正常现象
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 2e5;
int MODN;
struct Node
{
    int left,right;
    int maxi;
};
struct SegmentTree
{
    Node nd[MAXN*4+2];
    void init()
    {
        for(int i=1; i<=MAXN*4; i++)
        {
            nd[i].left = nd[i].right = nd[i].maxi = 0;
        }
    }
    void build(int lbound,int rbound,int pos,int a[])
    {
        nd[pos].left = lbound;
        nd[pos].right = rbound;
        if(lbound==rbound)
        {
            nd[pos].maxi = a[lbound];
            return;
        }
        int mid = (lbound+rbound)/2;
        build(lbound,mid,2*pos,a);
        build(mid+1,rbound,2*pos+1,a);
        nd[pos].maxi = max(nd[2*pos].maxi,nd[2*pos+1].maxi);
    }
    void modify(int bound,int val,int pos)
    {
        int mid = (nd[pos].left+nd[pos].right)/2;
        if(nd[pos].left==nd[pos].right)
        {
            nd[pos].maxi = val;
            return;
        }
        if(bound<=mid) modify(bound,val,2*pos);
        else modify(bound,val,2*pos+1);
        nd[pos].maxi = max(nd[2*pos].maxi,nd[2*pos+1].maxi);
    }
    int query(int lbound,int rbound,int pos)
    {
        int mid = (nd[pos].left+nd[pos].right)/2;
        if(lbound==nd[pos].left && rbound==nd[pos].right) return nd[pos].maxi;
        int ans;
        if(rbound<=mid) ans = query(lbound,rbound,2*pos);
        else if(lbound>mid) ans = query(lbound,rbound,2*pos+1);
        else ans = max(query(lbound,mid,2*pos),query(mid+1,rbound,2*pos+1));
        return ans;
    }
};
SegmentTree st;
int a[MAXN+2];
int p[MAXN+2];
int ql[MAXN+2];
int qr[MAXN+2];
int n,m,q;
int main()
{
    char ch[5];
    int x;
    n = q = 0;
    scanf("%d%d",&m,&MODN);
    for(int i=1; i<=m; i++)
    {
        scanf("%s",ch);
        switch(ch[0])
        {
            case 'A':
            {
                scanf("%d",&x);
                a[++n] = x;
                p[n] = q;
                break;
            }
            case 'Q':
            {
                scanf("%d",&x);
                ql[++q] = n-x+1;
                qr[q] = n;
                break;
            }
        }
    }
    st.init();
    st.build(1,n,1,a);
    int j = 1;
    while(j<=n && !p[j])
    {
        j++;
    }
    for(int i=1; i<=q; i++)
    {
        int ans = st.query(ql[i],qr[i],1);
        printf("%d\n",ans);
        while(j<=n && p[j]==i)
        {
            st.modify(j,(int)((long long)a[j]+ans)%MODN,1);
            j++;
        }
    }
    return 0;
}
												
											Luogu P1198 BZOJ 1012 最大数 (线段树)的更多相关文章
- bzoj 1012 基础线段树
		
原题传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1012 今儿一天状态不好,都没怎么刷题..快下课了,刷道水题.... 裸的线段树 /*** ...
 - BZOJ 1012【线段树】
		
题意: Q L 询问数列最后 L 个数中最大的数. A n 将 n + t ( t_init = 0 ), 然后插到最后去. 思路: 感觉动态地插入,很有问题. 数组地长度会时常变化,但是可以先预处理 ...
 - BZOJ.4184.shallot(线段树分治 线性基)
		
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
 - luogu P2574 XOR的艺术 (线段树)
		
luogu P2574 XOR的艺术 (线段树) 算是比较简单的线段树. 当区间修改时.\(1 xor 1 = 0,0 xor 1 = 1\)所以就是区间元素个数减去以前的\(1\)的个数就是现在\( ...
 - 【原创】洛谷 LUOGU P3373 【模板】线段树2
		
P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格式: 第 ...
 - 【原创】洛谷 LUOGU P3372 【模板】线段树1
		
P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别 ...
 - [BZOJ 4025]二分图(线段树分治+带边权并查集)
		
[BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...
 - BZOJ 1012 最大数maxnumber 线段树
		
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1012 题目大意: 见链接 思路: 直接用线段树模拟一下就可以了. #include&l ...
 - 洛谷 - P1198 - 最大数 - 线段树
		
https://www.luogu.org/problemnew/show/P1198 要问区间最大值,肯定是要用线段树的,不能用树状数组.(因为没有逆元?但是题目求的是最后一段,可以改成类似前缀和啊 ...
 
随机推荐
- 移植DirectFB于SOC3210(龙芯)【转】
			
本文转载自:http://blog.chinaunix.net/uid-25298908-id-120188.html 编译平台:龙芯.中标普华Linux桌面5 目标平台:SOC3210 一.获取源码 ...
 - How to Integrate .NET Projects with Jenkins
			
https://www.swtestacademy.com/jenkins-dotnet-integration/ 8) Unit Tests and Test Coverage Settings D ...
 - wesome-android
			
awesome-android Introduction android libs from github System requirements Android Notice If the lib ...
 - ZOJ 2314 无源汇可行流(输出方案)
			
Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge The terrorist group leaded by a ...
 - bzoj4197 [Noi2015]寿司晚宴——状压DP
			
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4197 首先,两个人选的数都互质可以看作是一个人选了一个数,就相当于选了一个质因数集合,另一个 ...
 - JDK5.0新特性(静态导入、自动装箱/拆箱、增强for循环、可变参数、枚举、泛形)
			
JDK5中新增了很多新的java特性,利用这些新语法可以帮助开发人员编写出更加高效.清晰,安全的代码. 这些新特性主要有:1.静态导入2.自动装箱/拆箱3.增强for循环4.可变参数5.枚举6.泛型7 ...
 - Shredding Company(dfs)
			
http://poj.org/problem?id=1416 题意:将一个数分成几部分,使其分割的各个数的和最大并且小于所给的数. 凌乱了..参考的会神的代码..orz... #include < ...
 - es6入门6--数组拓展运算符,Array.from()基本用法
			
本文只是作为ES6入门第九章学习笔记,在整理知识点的同时,会加入部分个人思考与解答,若想知道更详细的介绍,还请阅读阮一峰大神的ES6入门 一.拓展运算符 ES6中新增了拓展运算(...)三个点,它的作 ...
 - Python描述符:property()函数的小秘密
			
描述符:将某种特殊类型的类的实例指派给另一个类的属性(注意:这里是类属性,而不是对象属性).而这种特殊类型的类就是实现了__get__,__set__,__delete__这三个方法中的一个或多个的新 ...
 - MySQL实现递归查询
			
DROP FUNCTION IF EXISTS queryChildrenCaseInfo;CREATE FUNCTION queryChildrenCaseInfo(cId INT)RETURNS ...