算法训练 操作格子
2018-03-10 21:32
351 查看
问题描述有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。
思路:
线段树单点更新,维护区间和,区间最大值课题.
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int tree1[4*maxn],tree2[4*maxn];
void build(int l,int r,int d)
{
if ( l == r ){
tree1[d] = a[l];
tree2[d] = a[l];
return;
}
int mid = (l+r)/2;
build(l,mid,2*d);
build(mid+1,r,2*d+1);
tree1[d] = tree1[2*d]+tree1[2*d+1];
tree2[d] = max(tree2[2*d],tree2[2*d+1]);
return;
}
void update(int pos,int l,int r,int d,int num)
{
if ( l == r ){
tree1[d] = num;
tree2[d] = num;
return;
}
int mid = (l+r)/2;
if (pos <= mid) //左子树
update(pos,l,mid,2*d,num);
else //右子树
update(pos,mid+1,r,2*d+1,num);
tree1[d] = tree1[2*d]+tree1[2*d+1];
tree2[d] = max(tree2[2*d],tree2[2*d+1]);
return ;
}
int query(int l,int r,int L,int R,int d)
{
if (l == L && r == R){
return tree1[d];
}
int mid = (L+R)/2;
if (r <= mid){
return query(l,r,L,mid,2*d);
}
else if (l > mid)
return query(l,r,mid+1,R,2*d+1);
else //部分在左子树,部分在右子树
return query(l,mid,L,mid,2*d)+query(mid+1,r,mid+1,R,2*d+1);
}
int querymax(int l,int r,int L,int R,int d)
{
if (l == L && r == R){
return tree2[d];
}
int mid = (L+R)/2;
int m = 0;
if (r <= mid)
return max(querymax(l,r,L,mid,2*d),m);
else if (l > mid)
return max(querymax(l,r,mid+1,R,2*d+1),m);
else
return max(querymax(l,mid,L,mid,2*d),querymax(mid+1,r,mid+1,R,2*d+1));
}
int main()
{
int n,m,p,x,y;
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> a[i];
//建树
build(1,n,1);
for(int i = 0; i < m; i++){
cin >> p >> x >> y;
if ( p == 1 ){
update(x,1,n,1,y);
}
else if ( p == 2 ){
int sum = query(x,y,1,n,1);
cout << sum << endl;
}
else{
int maxn = querymax(x,y,1,n,1);
cout << maxn << endl;
}
}
return 0;
}
共有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。
思路:
线段树单点更新,维护区间和,区间最大值课题.
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int tree1[4*maxn],tree2[4*maxn];
void build(int l,int r,int d)
{
if ( l == r ){
tree1[d] = a[l];
tree2[d] = a[l];
return;
}
int mid = (l+r)/2;
build(l,mid,2*d);
build(mid+1,r,2*d+1);
tree1[d] = tree1[2*d]+tree1[2*d+1];
tree2[d] = max(tree2[2*d],tree2[2*d+1]);
return;
}
void update(int pos,int l,int r,int d,int num)
{
if ( l == r ){
tree1[d] = num;
tree2[d] = num;
return;
}
int mid = (l+r)/2;
if (pos <= mid) //左子树
update(pos,l,mid,2*d,num);
else //右子树
update(pos,mid+1,r,2*d+1,num);
tree1[d] = tree1[2*d]+tree1[2*d+1];
tree2[d] = max(tree2[2*d],tree2[2*d+1]);
return ;
}
int query(int l,int r,int L,int R,int d)
{
if (l == L && r == R){
return tree1[d];
}
int mid = (L+R)/2;
if (r <= mid){
return query(l,r,L,mid,2*d);
}
else if (l > mid)
return query(l,r,mid+1,R,2*d+1);
else //部分在左子树,部分在右子树
return query(l,mid,L,mid,2*d)+query(mid+1,r,mid+1,R,2*d+1);
}
int querymax(int l,int r,int L,int R,int d)
{
if (l == L && r == R){
return tree2[d];
}
int mid = (L+R)/2;
int m = 0;
if (r <= mid)
return max(querymax(l,r,L,mid,2*d),m);
else if (l > mid)
return max(querymax(l,r,mid+1,R,2*d+1),m);
else
return max(querymax(l,mid,L,mid,2*d),querymax(mid+1,r,mid+1,R,2*d+1));
}
int main()
{
int n,m,p,x,y;
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> a[i];
//建树
build(1,n,1);
for(int i = 0; i < m; i++){
cin >> p >> x >> y;
if ( p == 1 ){
update(x,1,n,1,y);
}
else if ( p == 2 ){
int sum = query(x,y,1,n,1);
cout << sum << endl;
}
else{
int maxn = querymax(x,y,1,n,1);
cout << maxn << endl;
}
}
return 0;
}
相关文章推荐
- 蓝桥杯 算法训练 操作格子
- 蓝桥杯算法训练——操作格子(线段树+单点更新+区间求和+求最大值)
- 蓝桥网 算法训练 操作格子
- 算法训练 操作格子
- 算法训练 操作格子
- 算法训练 操作格子
- 蓝桥杯 算法训练 操作格子 JAVA
- 算法训练 操作格子
- 算法训练 操作格子
- 算法训练 操作格子
- 蓝桥杯 算法训练 操作格子
- 蓝桥杯 ALGO-8 算法训练 操作格子(线段树)
- 蓝桥杯 算法训练 操作格子(线段树)
- 蓝桥杯-算法训练 操作格子
- 算法训练 操作格子
- 蓝桥杯 算法训练 操作格子 (最基本的线段树)
- 蓝桥杯 算法训练 操作格子 (线段树模板)
- 蓝桥杯 算法训练 操作格子
- 蓝桥杯 算法训练 操作格子 [ 线段树 ]
- 算法训练 操作格子