算法训练 操作格子 线段树板子题

问题描述

有n个格子,从左到右放成一排,编号为1-n。

共有m次操作,有3种操作类型:

1.修改一个格子的权值,

2.求连续一段格子权值和,

3.求连续一段格子的最大值。

对于每个2、3操作输出你所求出的结果。

输入格式

第一行2个整数n,m。

接下来一行n个整数表示n个格子的初始权值。

接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。

输出格式

有若干行,行数等于p=2或3的操作总数。

每行1个整数,对应了每个p=2或3操作的结果。

样例输入

4 3
1 2 3 4
2 1 3
1 4 3
3 1 4

样例输出

6
3

数据规模与约定

对于20%的数据n <= 100,m <= 200。

对于50%的数据n <= 5000,m <= 5000。

对于100%的数据1 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000。

  1 #include<bits/stdc++.h>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<vector>
  7 #define ll __int64
  8 #define PI acos(-1.0)
  9 #define mod 1000000007
 10 using namespace std;
 11 int n,m;
 12 struct node
 13 {
 14     int l,r;
 15     int value;
 16     int maxn;
 17 }tree[400005];
 18 int exm;
 19 void  buildtree(int root ,int l,int r)
 20 {
 21      tree[root].l=l;
 22      tree[root].r=r;
 23     if(l==r)
 24     {
 25         scanf("%d",&exm);
 26         tree[root].value=tree[root].maxn=exm;
 27         return;
 28     }
 29     int mid=(l+r)>>1;
 30     buildtree(root<<1,l,mid);
 31     buildtree(root<<1|1,mid+1,r);
 32     tree[root].maxn=max(tree[root<<1].maxn,tree[root<<1|1].maxn);
 33     tree[root].value=tree[root<<1].value+tree[root<<1|1].value;
 34 }
 35 void update(int root ,int what,int c)
 36 {
 37     if(tree[root].l==tree[root].r&&tree[root].r==what)
 38     {
 39         tree[root].maxn=tree[root].value=c;
 40         return;
 41     }
 42     int mid=(tree[root].l+tree[root].r)>>1;
 43     if(what<=mid)
 44         update(root<<1,what,c);
 45     else
 46         update(root<<1|1,what,c);
 47     tree[root].maxn=max(tree[root<<1].maxn,tree[root<<1|1].maxn);
 48     tree[root].value=tree[root<<1].value+tree[root<<1|1].value;
 49 }
 50 int query1(int root,int l,int r)
 51 {
 52     if(tree[root].l==l&&tree[root].r==r)
 53     {
 54         return tree[root].value;
 55     }
 56     int mid=(tree[root].l+tree[root].r)>>1;
 57     if(r<=mid)
 58          return query1(root<<1,l,r);
 59     else
 60     {
 61         if(l>mid)
 62           return query1(root<<1|1,l,r);
 63         else
 64           return query1(root<<1,l,mid)+query1(root<<1|1,mid+1,r);
 65     }
 66 }
 67 int query2(int root,int l,int r)
 68 {
 69     if(tree[root].l==l&&tree[root].r==r)
 70     {
 71         return tree[root].maxn;
 72     }
 73     int mid=(tree[root].l+tree[root].r)>>1;
 74     if(r<=mid)
 75          return query2(root<<1,l,r);
 76     else
 77     {
 78         if(l>mid)
 79           return query2(root<<1|1,l,r);
 80         else
 81           return max(query2(root<<1,l,mid),query2(root<<1|1,mid+1,r));
 82     }
 83 }
 84 int main()
 85 {
 86     int q,w,e;
 87     scanf("%d %d",&n,&m);
 88     buildtree(1,1,n);
 89     for(int i=1;i<=m;i++)
 90     {
 91         scanf("%d %d %d",&q,&w,&e);
 92         if(q==1)
 93             update(1,w,e);
 94         if(q==2)
 95             printf("%d\n",query1(1,w,e));
 96         if(q==3)
 97             printf("%d\n",query2(1,w,e));
 98     }
 99     return 0;
100 }
时间: 2024-12-17 19:26:47

算法训练 操作格子 线段树板子题的相关文章

蓝桥杯 算法训练 操作格子 [ 线段树 ]

传送门 算法训练 操作格子 时间限制:1.0s   内存限制:256.0MB 锦囊1 锦囊2 锦囊3 问题描述 有n个格子,从左到右放成一排,编号为1-n. 共有m次操作,有3种操作类型: 1.修改一个格子的权值, 2.求连续一段格子权值和, 3.求连续一段格子的最大值. 对于每个2.3操作输出你所求出的结果. 输入格式 第一行2个整数n,m. 接下来一行n个整数表示n个格子的初始权值. 接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x

算法训练 操作格子

算法训练 操作格子 时间限制:1.0s   内存限制:256.0MB 问题描述 有n个格子,从左到右放成一排,编号为1-n. 共有m次操作,有3种操作类型: 1.修改一个格子的权值, 2.求连续一段格子权值和, 3.求连续一段格子的最大值. 对于每个2.3操作输出你所求出的结果. 输入格式 第一行2个整数n,m. 接下来一行n个整数表示n个格子的初始权值. 接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示

线段树- 算法训练 操作格子

问题描述 有n个格子,从左到右放成一排,编号为1-n. 共有m次操作,有3种操作类型: 1.修改一个格子的权值, 2.求连续一段格子权值和, 3.求连续一段格子的最大值. 对于每个2.3操作输出你所求出的结果. 输入格式 第一行2个整数n,m. 接下来一行n个整数表示n个格子的初始权值. 接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值. 输出格式 有若干行,行数等于p=2

蓝桥杯操作格子(线段树)

赤裸裸的线段树 #include<iostream> #include<cstdio> #include<algorithm> #define Max(a,b) (a>b)?a:b using namespace std; const int MAX_N=100005*4;//至少要开2*n-1个空间 typedef long long LL; struct node{ int l,r,max; LL sum; }; node a[MAX_N]; void bui

权值线段树板子题

https://www.luogu.org/problem/P1168 #include <bits/stdc++.h> using namespace std; const int maxn=1e5+5; int tree[maxn*4]; int dtc[maxn]; int a[maxn]; void pushup(int root) { tree[root]=tree[root<<1]+tree[root<<1|1]; } void update(int roo

蓝桥杯-操作格子(线段树)

#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #include<vector> #include<cmath> #define ll __int64 #define

HDU 4027 Can you answer these queries? 线段树裸题

题意: 给定2个操作 0.把区间的每个数sqrt 2.求和 因为每个数的sqrt次数很少,所以直接更新到底,用个标记表示是否更新完全(即区间内的数字只有0,1就不用再更新了) #include<stdio.h> #include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<queue> #include<set> #incl

Codeforces Round #393 (Div. 2) (8VC Venture Cup 2017 - Final Round Div. 2 Edition) E - Nikita and stack 线段树好题

http://codeforces.com/contest/760/problem/E 题目大意:现在对栈有m个操作,但是顺序是乱的,现在每输入一个操作要求你输出当前的栈顶, 注意,已有操作要按它们的时间顺序进行. 思路:线段树好题啊啊,我们把push当成+1, pop当成-1,按操作的位置建立线段树,那么如何 寻找栈顶呢,我们计算每个点的后缀,栈顶就是下标最大的>0的后缀,我们拿后缀建立线段树, 剩下的就是区间加减法,和求区间最大值啦. #include<bits/stdc++.h>

P2023 [AHOI2009] 维护序列(线段树水题)

题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值. 输入输出格式 输入格式: 第一行两个整数N和P(1≤P≤1000000000).第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N).第三行有一个整