藍橋杯 演算法訓練 操作格子 (線段樹)
藍橋杯歷年真題題目及題解目錄彙總
演算法訓練 操作格子
時間限制: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時表示求區間[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。
學到的東西是初始化線段樹資料的時候直接插入會比較好,而不是在建樹的時候push_up初始化,但是實際沒多大區別,這題官網沒給java好的資料,c++才能過,網上大多數的題解也是提交超時的,呵呵!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<sstream>
#include<cstdlib>
#include<queue>
using namespace std;
const int N = 400005;
int MAX(int a,int b){
return a>b?a:b;
}
struct node{
int l,r,sum,max;
}a[N];
void build(int n,int l,int r){
a[n].l = l;
a[n].r = r;
a[n].max = 0;
a[n].sum = 0;
if(l == r) return;
build(n*2,l,(l+r)/2);
build(n*2+1,(l+r)/2+1,r);
}
void insert(int n,int pos,int num){
a[n].sum += num; //更新加和
if(a[n].max < num) a[n].max = num;//更新最大值
if(a[n].l == a[n].r) return;
int mid = (a[n].l+a[n].r)/2;
if(pos <= mid) insert(n*2,pos,num);
else insert(n*2+1,pos,num);
}
void change(int n,int pos,int num){
if(pos == a[n].l && pos == a[n].r){//找到位置
a[n].max = num;
a[n].sum = num;
return;
}
int mid = (a[n].l + a[n].r )/2;
if(pos <= mid) change(n*2,pos,num);
else change(n*2+1,pos,num);
a[n].sum = a[n*2].sum + a[n*2+1].sum;
a[n].max = MAX(a[n*2].max,a[n*2+1].max);
}
int qsum(int n,int l,int r){
if(l == a[n].l && r == a[n].r){//範圍相同,直接返回
return a[n].sum;
}
int mid = (a[n].l+a[n].r)/2;
if(r<=mid){//範圍在左邊
return qsum(n*2,l,r);
}
else if(mid<l){//範圍在右邊
return qsum(n*2+1,l,r);
}
else{//一半在左,一半在右
return qsum(n*2,l,mid)+qsum(n*2+1,mid+1,r);
}
}
int qmax(int n,int l,int r){
if(l == a[n].l && r == a[n].r){//範圍相同,直接返回
return a[n].max;
}
int mid = (a[n].l+a[n].r)/2;
if(r<=mid){//範圍在左邊
return qmax(n*2,l,r);
}
else if(mid<l){//範圍在右邊
return qmax(n*2+1,l,r);
}
else{//一半在左,一半在右
return MAX(qmax(n*2,l,mid),qmax(n*2+1,mid+1,r));
}
}
int main(){
int n,m;
cin>>n>>m;
build(1,1,n);
for(int i =1;i<=n;i++){
int x;
cin>>x;
insert(1,i,x);
}
for(int i =0;i<m;i++){
int p,a,b;
cin>>p>>a>>b;
switch(p){
case 1:change(1,a,b); break;
case 2:cout<<qsum(1,a,b)<<endl; break;
case 3:cout<<qmax(1,a,b)<<endl; break;
}
}
return 0;
}
import java.util.Scanner;
public class 藍橋杯_操作格子 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
tree = new Segtree[4*n+5];
for(int i=1;i<=4*n+4;i++)
tree[i] = new Segtree();
buildtree(1, 1, n);
for(int i=1;i<=n;i++)
insert(1, i, in.nextInt());;
while(m-->0) {
int Q = in.nextInt();
int x = in.nextInt();
int y = in.nextInt();
if(Q==1)
updata(1, x, y);
else if(Q==2)
System.out.println(querySum(1, 1, n, x, y));
else if(Q==3)
System.out.println(queryMax(1, 1, n, x, y));
}
}
static int n,m;
static Segtree[] tree;
static class Segtree {
int l,r,sum,max;
public Segtree(int l,int r) {
this.l = l;
this.r = r;
}
public Segtree() {}
}
static void buildtree(int now,int l,int r) {
tree[now].l = l;
tree[now].r = r;
if(l==r)
return;
int mid = l + (r-l)/2;
buildtree(2*now, l, mid);
buildtree(2*now+1, mid+1, r);
// tree[now].sum = tree[2*now].sum + tree[2*now+1].sum;
// tree[now].max = Math.max(tree[2*now].max, tree[2*now+1].max);
}
static void insert(int now,int pos,int num){
tree[now].sum+=num;
tree[now].max=Math.max(tree[now].max, num);
if(tree[now].l == tree[now].r)
return;
int mid = tree[now].l + (tree[now].r-tree[now].l)/2;
if(pos<=mid)
insert(2*now, pos, num);
else
insert(2*now+1, pos, num);
}
static void updata(int now,int pos,int num){
if(tree[now].l == tree[now].r) {
tree[now].sum=num;
tree[now].max=num;
return;
}
int mid = tree[now].l + (tree[now].r-tree[now].l)/2;
if(pos<=mid)
updata(2*now, pos, num);
else
updata(2*now+1, pos, num);
tree[now].sum = tree[2*now].sum + tree[2*now+1].sum;
tree[now].max = Math.max(tree[2*now].max, tree[2*now+1].max);
}
static int querySum(int now,int l,int r,int x,int y) {
if(r<x || l>y)
return 0;
if(x<=l && y>=r)
return tree[now].sum;
int mid = l + (r-l)/2;
int ans = 0;
if(x<=mid)
ans+=querySum(2*now, l, mid, x, y);
if(y>mid)
ans+=querySum(2*now+1, mid+1, r, x, y);
return ans;
}
static int queryMax(int now,int l,int r,int x,int y) {
if(y<l || x>r)
return -1;
if(x<=l && y>=r)
return tree[now].max;
int mid = l + (r-l)/2;
int ans = -1;
if(x<=mid)
ans = Math.max(ans, queryMax(2*now, l, mid, x, y));
if(y>mid)
ans = Math.max(ans, queryMax(2*now+1, mid+1, r, x, y));
return ans;
}
}
下面這個也一樣是30%,其實原則上沒上面的優化。不過沒多大區別
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
tree = new Segtree[4*n+5];
for(int i=1;i<=4*n+4;i++)
tree[i] = new Segtree();
buildtree(1, 1, n);
for(int i=1;i<=n;i++)
insert(1, i, in.nextInt());;
while(m-->0) {
int Q = in.nextInt();
int x = in.nextInt();
int y = in.nextInt();
if(Q==1)
insert(1, x, y);
else if(Q==2)
System.out.println(querySum(1, 1, n, x, y));
else if(Q==3)
System.out.println(queryMax(1, 1, n, x, y));
}
}
static int n,m;
static Segtree[] tree;
static class Segtree {
int l,r,sum,max;
public Segtree(int l,int r) {
this.l = l;
this.r = r;
}
public Segtree() {}
}
static void buildtree(int now,int l,int r) {
tree[now].l = l;
tree[now].r = r;
if(l==r)
return;
int mid = l + (r-l)/2;
buildtree(2*now, l, mid);
buildtree(2*now+1, mid+1, r);
// tree[now].sum = tree[2*now].sum + tree[2*now+1].sum;
// tree[now].max = Math.max(tree[2*now].max, tree[2*now+1].max);
}
static void insert(int now,int pos,int num){
if(tree[now].l == tree[now].r) {
tree[now].sum=num;
tree[now].max=num;
return;
}
int mid = tree[now].l + (tree[now].r-tree[now].l)/2;
if(pos<=mid)
insert(2*now, pos, num);
else
insert(2*now+1, pos, num);
tree[now].sum = tree[2*now].sum + tree[2*now+1].sum;
tree[now].max = Math.max(tree[2*now].max, tree[2*now+1].max);
}
// static int querySum(int now,int l,int r,int x,int y) {
// if(r<x || l>y)
// return 0;
// if(x<=l && y>=r)
// return tree[now].sum;
//
// int mid = l + (r-l)/2;
// return querySum(2*now, l, mid, x, y) + querySum(2*now+1, mid+1, r, x, y);
// }
static int querySum(int now,int l,int r,int x,int y) {
if(r<x || l>y)
return 0;
if(x<=l && y>=r)
return tree[now].sum;
int mid = l + (r-l)/2;
int ans = 0;
if(x<=mid)
ans+=querySum(2*now, l, mid, x, y);
if(y>mid)
ans+=querySum(2*now+1, mid+1, r, x, y);
return ans;
}
static int queryMax(int now,int l,int r,int x,int y) {
if(y<l || x>r)
return -1;
if(x<=l && y>=r)
return tree[now].max;
int mid = l + (r-l)/2;
return Math.max(queryMax(2*now, l, mid, x, y), queryMax(2*now+1, mid+1, r, x, y));
}
}
相關文章
- 藍橋杯—演算法訓練演算法
- 藍橋杯--演算法訓練演算法
- [藍橋杯][演算法提高VIP]分蘋果 線段樹演算法蘋果
- 藍橋杯 (java)演算法訓練 數對Java演算法
- 演算法訓練 字首表示式 (藍橋杯)演算法
- [藍橋杯][演算法訓練VIP]方格取數演算法
- 藍橋杯 演算法訓練 素因子去重(Java)演算法Java
- 藍橋杯 演算法訓練 K好數(Java解題)演算法Java
- [Java] 藍橋杯ALGO-117 演算法訓練 友好數JavaGo演算法
- 藍橋杯訓練--母牛的故事(很清晰的思路)
- 藍橋杯:入門訓練 Fibonacci數列
- [藍橋杯][演算法提高VIP]上帝造題五分鐘 (線段樹+區間最小值)演算法
- 藍橋杯 演算法訓練 區間k大數查詢 (Java解題)演算法Java
- 問題 1462: [藍橋杯][基礎練習VIP]Huffuman樹
- 藍橋杯學習路線
- 藍橋杯練習系統題目集
- 【藍橋杯】試題 歷屆試題 剪格子(python解法+java解法)PythonJava
- 藍橋杯 排序排序
- 藍橋杯:基礎練習 查詢整數
- 藍橋杯 【基礎練習】 特殊迴文數
- 藍橋杯演算法提高——字串匹配(Java)演算法字串匹配Java
- 藍橋杯 演算法提高 字串壓縮演算法字串
- 藍橋杯-N皇后
- 藍橋杯真題
- 藍橋杯-AB路線(詳細原創)
- [藍橋杯][基礎練習VIP]矩形面積交
- 藍橋杯練習試題程式碼及講解
- [藍橋杯][演算法提高VIP]尤拉函式演算法函式
- [藍橋杯][演算法提高VIP]超級瑪麗演算法
- [藍橋杯][演算法提高VIP]大數加法演算法
- 藍橋杯年號字串字串
- 藍橋杯-帶分數
- 藍橋杯-翻硬幣
- 藍橋杯-螞蟻感冒
- 藍橋杯 計算方程
- 藍橋杯-座次問題
- 藍橋杯-長草(BFS)
- 藍橋杯-日期問題