洛谷 U361 序列操作(NOIP模拟赛T2)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 U361 序列操作(NOIP模拟赛T2)相关的知识,希望对你有一定的参考价值。

题目链接:https://www.luogu.org/problem/show?pid=U361

题目背景

夏令营

题目描述

小B有一个整数序列a[1..N],初始时序列中所有元素均为0。他会在序列上进行下面两种操作,操作共M个:

  1. A l r x:将a[l..r]均加上x。

  2. Q l r:询问a[l..r]中的最大值。

输入输出格式

输入格式:

 

第一行,两个整数N, M。

接下来的M行,每行一个操作。

 

输出格式:

 

设询问操作有T个,则输出T行,每行一个整数,表示询问操作对应的答案。

 

输入输出样例

输入样例#1:
5 5
A 1 4 1
A 2 5 2
Q 1 4
A 3 4 -2
Q 3 5
输出样例#1:
3
2

 

很显然地就是一个线段树,甚至几乎是裸的......

但是还是有许多细节需要注意,每次数据结构都是一写就错......

↑你说为什么我放弃了上百毫秒的时间写结构体,因为这样不容易错qwq

(老大:也没看出来你不容易错,还不是改了半天- -)

 

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 const int MAXN = 100000 + 5;
 7 struct seg//建树 
 8 {
 9     int l,r;
10     int max = 0;
11     int lazy;
12 } tree[MAXN << 2];
13 
14 int max(int a,int b)
15 {
16     return a>b?a:b; 
17 }
18 
19 void build(int o,int l,int r)
20 {
21     tree[o].l = l;
22     tree[o].r = r;
23     if(l == r)
24         return;
25     int mid = (l + r) >> 1;
26     build(o << 1,l,mid);
27     build(o << 1 | 1,mid + 1,r);
28 }
29 
30 void putdown(int o)
31 {
32     tree[o << 1].lazy += tree[o].lazy;
33     tree[o << 1 | 1].lazy += tree[o].lazy;
34     tree[o << 1].max += tree[o].lazy;
35     tree[o << 1 | 1].max += tree[o].lazy;
36     tree[o].lazy = 0;
37 }
38 
39 void modify2(int l, int r, int k,int o)
40 {
41     if(l <= tree[o].l && r >= tree[o].r)
42     {
43         tree[o].max += k;
44         tree[o].lazy += k;
45         return;    
46     }
47     int mid = (tree[o].l + tree[o].r) >> 1;
48     if(tree[o].lazy)    putdown(o);
49     if(mid >= l)    modify2(l, r, k, o << 1);
50     if(mid < r)     modify2(l, r, k, o << 1 | 1);
51     tree[o].max = max(tree[o << 1].max , tree[o << 1 | 1].max);
52 }
53 
54 int ask(int l,int r,int o)//询问操作 
55 {
56     if(tree[o].l >= l && tree[o].r <= r)
57     {
58         return tree[o].max;
59     }
60     if(tree[o].lazy)    putdown(o);
61     int ans = -2147483647;//由于每次操作增加的x可能是负值,ans要尽可能小 
62     int mid = (tree[o].l + tree[o].r) >>1;
63     if(mid >= l) ans = max(ans,ask(l,r,o << 1));
64     if(mid < r) ans = max(ans,ask(l,r,o <<1|1)); 
65     return ans;
66 }
67 
68 int main()
69 {
70     int a,b,m,n,x;
71     scanf("%d%d",&n,&m);
72     build(1,1,n);
73     char op;
74     for(int i = 1;i <= m;i ++)
75     {
76         scanf("%c",&op);
77         while(op < A)
78             scanf("%c",&op);
79         scanf("%d%d",&a,&b);
80         if(op == A)
81         {
82             scanf("%d",&x);
83             modify2(a,b,x,1);
84         }
85         if(op == Q)
86         {
87             int t = ask(a,b,1);
88             printf("%d\n",t);
89         }
90     }
91     return 0;    
92 }

 线段树的易错点还是很多的,比如忘写返回值、大于小于号写反、开闭区间写错、函数参数位置颠倒……(没错,以上问题博主都出现过QAQ)写的时候一定要仔细...

以上是关于洛谷 U361 序列操作(NOIP模拟赛T2)的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2017模拟赛 senior 6.29 T2 小T的钢琴(piano)

EZ 2018 05 13 NOIP2018 模拟赛(十三)

学军NOIP2016模拟赛1

洛谷P1052NOIP2005提高T2过河

洛谷 [P1314] 聪明的质检员(NOIP2011 D2T2)

洛谷 P1098 字符串的展开(NOIp2007提高组T2)