P1198最大数——线段树点修改&&模板题

题目

题目链接

大意:维护一个数列,有两种操作:

  • 查询操作Q  L:查询当前数列中末尾L个数中的最大的数
  • 插入操作A  n:将n加上t再对D取模,将所得值插入数列末尾

解决方案

由题意知,只有两种操作:单点修改、区间查询

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3
 4 typedef long long ll;
 5 const ll INF = (ll)1 << 60;
 6 const int maxn = 200000 + 10;
 7 ll maxv[maxn << 2];
 8 int n;
 9 ll mod;
10
11 int ql, qr;    //查询[ql, qr]中的最小值
12 ll query(int o,int L,int R)
13 {
14     //printf("o:%d  L:%d  R:%d\n", o, L, R);
15     int M = L + (R - L) / 2;
16     ll ans = -INF;
17     if(ql <= L && R <= qr)  return maxv[o];
18     if(ql <= M)  ans = max(ans, query(2*o, L, M));
19     if(qr > M)  ans = max(ans, query(2*o+1, M+1, R));
20     return ans;
21 }
22
23 ll P, v;  //修改A[p]=v
24 void update(int o, int L, int R)
25 {
26     int M = L + (R-L)/2;
27     if(L == R)  maxv[o] = v;  //更新叶子结点
28     else
29     {
30         if(P <= M)  update(2*o, L ,M);
31         else  update(2*o+1, M+1, R);
32         maxv[o] = max(maxv[2*o], maxv[2*o+1]);  //更新非叶子结点
33     }
34 }
35
36 void print_debug(int o, int L, int R)
37 {
38     printf("o:%d  L:%d  R:%d  maxv:%lld\n", o, L, R,  maxv[o]);
39     if(R > L)
40     {
41         int M = L + (R - L) / 2;
42         print_debug(2*o, L, M);
43         print_debug(2*o+1, M+1, R);
44     }
45 }
46
47 int main()
48 {
49     scanf("%d%lld", &n, &mod);
50     char order[3];
51     int cnt = 0;
52     ll val, t = 0;
53
54     for(int i = 1;i <= (n <<2);i++)  maxv[i] = -INF;  //初始化
55
56     for(int i = 0;i < n;i++)
57     {
58         scanf("%s", order);
59         if(order[0] == ‘A‘)
60         {
61             scanf("%lld", &val);
62             P = ++cnt;
63             v = (val + t + mod) % mod;
64             update(1, 1, n);
65             //print_debug(1, 1, n);
66         }
67         else
68         {
69             int L;
70             //printf("cnt: %d\n", cnt);
71             scanf("%d", &L);
72             ql = cnt - L + 1; qr = cnt;
73             t = query(1, 1, n);
74             printf("%lld\n", t);
75             //print_debug(1, 1, n);
76         }
77     }
78
79     return 0;
80 }

原文地址:https://www.cnblogs.com/lfri/p/11144813.html

时间: 2024-10-14 23:03:58

P1198最大数——线段树点修改&&模板题的相关文章

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 )

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 ) 这是大白书上的例题,一直放着没有去A掉,这是一道线段树区间修改的好题. 线段树中需要维护三个域 ,max, min, sum,也就是区间最大值,最小值,区间和 题目大意: r 行 c 列 的全0矩阵,支持三个操作 1 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素增加v 2 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素设为v 3 x1 y1

HDU 1166 敌兵布阵 (我的树状数组加线段树点修改模板)

思路:本题因为是点修改,所以我们可以用线段树或者是树状数组了.线段树的基本操作我在我的代码中会具体体现,关键是要理解下面这幅图,具体的思想大家可以去看看其他的资料 线段树AC代码: #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define N 50005 int num

线段树区间修改模板

本来打算把大白书第三章一口气攻下来的,但是这个线段树也是卡了好久. 不敢过题太快,怕自己走马观花到头来结果什么都不会. 可也不能再拖了,在做题中也许有更多的体会. 模板一:1 L R v 表示区间[L, R]所有元素都加上v2 L R   表示查询区间[L, R]的sum, min, maxsumv[o]的定义为:如果只执行节点o及其子孙节点的中的add操作,节点o对应区间中所有数之和 1 //线段树区间修改 2 //1 L R v 表示区间[L, R]所有元素都加上v 3 //2 L R 表示

线段树点修改模板(HDU1754)

很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多组测试,请处理到文件结束.在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目.学生ID编号分别从1编到N.第二行包含N个整数,代表这N个学生的初始成绩,其中第

codevs 1082 线段树练习3 模板题

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 long long a[2000003],sum[10000003],add[10000003],n; 6 void pushup(long long rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];} 7 void build(long long l,

HDU1698:Just a Hook(线段树区域更新模板题)

http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same len

FZU Problem 2171 防守阵地 II (线段树区间更新模板题)

http://acm.fzu.edu.cn/problem.php?pid=2171 成段增减,区间求和.add累加更新的次数. #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <string> #include <algorithm> #include <stri

线段树区间修改 P3372 【模板】线段树 1

题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和 输出格式: 输出包含若干行整

【模板】线段树区间修改

区间修改: 区间修改过程类似于区间询问,例如将[ul, ur]内的所有元素都加上v,则进行如下操作: 当当前区间被区间[ul, ur]所包含时, 当前的节点值加上区间长度(r - l  + 1)乘以v 对当前节点的lazy-tag加上v,修改结束 否则,将当前节点的lazy-tag下传,分别修改左孩子和右孩子(一定条件下),然后更新此节点的值 lazy-tag下传: 如果当前节点没有lazy-tag,直接return 否则:1. 将左孩子右孩子分别加上lazy-tag * 区间长度的值  2.