第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-8 算法训练 操作格子 线段树

简介: 第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-8 算法训练 操作格子 线段树

第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-8 算法训练 操作格子 线段树


前言

       最近的一些文章都可能会很碎,写到哪里是哪里,过一阵子会具体的整理一遍,这里其它的类型题先往后排一排,因为蓝桥最后考的也就是对题目逻辑的理解能力,也就是dp分析能力了,所以就主要目标定在这里,最近的题目会很散,很多,基本上都是网罗全网的一些dp练习题进行二次训练,准备比赛的学生底子薄的先不建议看啊,当然,脑子快的例外,可以直接跳过之前的一切直接来看即可,只需要你在高中的时候数学成绩还可以那就没啥问题,其实,dp就是规律总结,我们只需要推导出对应题目的数学规律就可以直接操作,可能是一维数组,也可能是二维数组,总体来看二维数组的较多,但是如果能降为的话建议降为,因为如果降为起来你看看时间复杂度就知道咋回事了,那么在这里祝大家能无序的各种看明白,争取能帮助到大家。


算法训练 操作格子

资源限制

内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s

问题描述

有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

题解:

C语言

#include <stdio.h>  
#define N 100000  
#define A 1000  
#define B 100  
int sum(int* a, int m, int n)  
{  
   int i,s=0;  
   for (i=m;i<=n;i++)  
       s+=a[i];  
   return s;  
}  
int max(int* a, int m, int n)  
{  
   int i,s=a[m];  
   for (i=m+1;i<=n;i++)  
       if (s<a[i])  
           s=a[i];  
   return s;  
}  
int main()  
{  
   int i,j,k,m,n;  
   int a[100000],b[100000][3],c[A][2]={0};  
   scanf("%d%d",&n,&m);  
   for (i=0; i<n;i++)  
       scanf("%d",&a[i]);  
   for (i=0;i<m;i++)  
       for (j=0;j<3;j++)  
           scanf("%d", &b[i][j]);  
   for (i=0;i<(n+B-1)/B;i++)  
   {  
       c[i][0]=c[i][1]=a[i * B];  
       for (j=i*B+1;j<i*B+B && j<n;j++)  
       {  
           c[i][0]+=a[j];  
           if (c[i][1]<a[j])  
               c[i][1]=a[j];  
       }  
   }  
   for (i=0;i<m;i++)  
   {  
       if (b[i][0]==1)  
       {  
           c[(b[i][1]-1)/B][0]+=b[i][2]-a[b[i][1]-1];  
           k=(b[i][1]-1)/B;  
           if (c[k][1]<=b[i][2])  
           {  
               c[k][1]=b[i][2];  
           }  
           else if (a[b[i][1]-1]==c[k][1])  
           {  
               a[b[i][1]-1]=b[i][2];  
               c[k][1]=max(a,k*B,k*B+B>n ? n-1 : k*B+B-1);  
           }  
           a[b[i][1]-1]=b[i][2];  
       }  
       else if(b[i][0]==2)  
       {  
           int s=0;  
           b[i][1]--, b[i][2]--;  
           int o=b[i][2]/B-b[i][1]/B;  
           if (o<2)  
           {  
               s=sum(a,b[i][1],b[i][2]);  
           }  
           else  
           {  
               s=sum(a,b[i][1],(b[i][1]+B)/B*B-1);  
               s+=sum(a, b[i][2]/B*B, b[i][2]);  
               for (j = b[i][1]/B+1;j<b[i][2]/B;j++)  
                   s += c[j][0];  
           }  
           printf("%d\n",s);  
       }  
       else if (b[i][0]==3)  
       {  
           int s = 0,t;  
           b[i][1]--, b[i][2]--;  
           int o=b[i][2]/B-b[i][1]/B;  
           if (o<2)  
           {  
               s=max(a, b[i][1],b[i][2]);  
           }  
           else  
           {  
               s=max(a,b[i][1],(b[i][1]+B)/B*B-1);  
               t=max(a,b[i][2]/B*B,b[i][2]);  
               if (s<t)s=t;  
               for (j=b[i][1]/B+1;j<b[i][2]/B;j++)  
                   if (s<c[j][1])  
                       s=c[j][1];  
           }  
           printf("%d\n",s);  
       }  
   }  
   return 0;  
}

C++语言

#include <cstdio>
#include <algorithm>
struct Tree
{
    int sum, max;
};
Tree tree[1 << 18];
void scan(int &n)
{
    char c;
    
    c = getchar();
    if (c == EOF) {
        return ;
    }
    while (c < '0' || c > '9') {
        c = getchar();
    }
    n = c - '0';
    while (c = getchar(), c >= '0' && c <= '9') {
        n *= 10;
        n += c - '0';
    }
}
void put(int n)
{
    int cnt = 0;
    char s[16];
    
    if (n == 0) {
        putchar('0');
        return ;
    }
    for( ; n; n /= 10) {
        s[cnt++] = n % 10 + '0';
    }
    while (cnt--) {
        putchar(s[cnt]);
    }
}
void update(int n, int v)
{
    for (n += (1 << 17),tree[n].sum = tree[n].max = v, n >>= 1; n; n >>= 1) {
        tree[n].max = std::max(tree[n + n].max, tree[n + n + 1].max);
        tree[n].sum = tree[n + n].sum + tree[n + n + 1].sum;
    }
}
int query(int s, int t, int func)
{
    int sum = 0, max = 0;
    
    for (s += (1 << 17) - 1, t += (1 << 17) + 1; s ^ t ^ 1; s >>= 1, t >>= 1) {
        if (~s & 1) {
            sum += tree[s ^ 1].sum;
            max = std::max(max, tree[s ^ 1].max);
        }
        if (t & 1) {
            sum += tree[t ^ 1].sum;
            max = std::max(max, tree[t ^ 1].max);
        }
    }
    return func ? max : sum;
}
int main()
{
    int n, m, i, a, b, c;
    
    scan(n);scan(m);
    for (i = 1; i <= n; ++i) {
        scan(a);
        update(i, a);
    }
    while (m--) {
        scan(c);scan(a);scan(b);
        c == 1 && (update(a, b), 0);
        c == 2 && (put(query(a, b, 0)), putchar('\n'), 0);
        c == 3 && (put(query(a, b, 1)), putchar('\n'), 0);
    }
    return 0;
}

Java语言

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
  
  static int[] array;
  
  static long []mark;
  
  static long []Tree;
  
  static int[] Max;
  public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub
    StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    
    PrintWriter pt=new PrintWriter(System.out);
    
    st.nextToken();
    
    int n=(int)st.nval;
    
    array=new int[n+1];//图方便从1开始
    
    mark=new long[4*n+4];
    
    Tree=new long[4*n+4];
    
    Max=new int[4*n+4];
    
    st.nextToken();
    int m=(int)st.nval;
    
    for(int i=1;i<=n;i++) {
      st.nextToken();
      array[i]=(int)st.nval;
    }
    
    build(1,n,1);
    
    for(int i=0;i<m;i++) {
      st.nextToken();
      if((int)st.nval==1) {
        st.nextToken();
        int a=(int)st.nval;
        st.nextToken();
        int v=(int)st.nval;
        
        update(a,a,v,1,1,n);
      }
      else if((int)st.nval==2){
        st.nextToken();
        int a=(int)st.nval;
        st.nextToken();
        int b=(int)st.nval;
        pt.println(query(a, b, 1, 1, n));
      }
      else {
        st.nextToken();
        int a=(int)st.nval;
        st.nextToken();
        int b=(int)st.nval;
        pt.println(getMax(a, b, 1, 1, n));
      }
    }
    pt.close();
    
    
    
  }
  
  
  public static void build(int l,int r,int p) {
    
    
    if(l==r) {
      Tree[p]=array[l];
      Max[p]=array[l];
    }
    else {
      int mid=l+(r-l)/2;
      build(l,mid,p*2);
      build(mid+1,r,p*2+1);
      Tree[p]=Tree[p*2]+Tree[p*2+1];
      Max[p]=Math.max(Max[p*2], Max[p*2+1]);
          
    }
    
  }
  
  
  public static void update(int l,int r,int d,int p,int nowL,int nowR) {
    
    if(r<nowL||l>nowR)
      return;
    if(l<=nowL&&r>=nowR) {
      Tree[p]=d;//懒标记的规则就是在更新当前的mark之前 已经修改了当前的tree的值
        Max[p]=d;
    }
    else {
      
      int mid=nowL+(nowR-nowL)/2;
      update(l,r,d,p*2,nowL,mid);
      update(l,r,d,p*2+1,mid+1,nowR);
      Tree[p]=Tree[p*2]+Tree[p*2+1];
      Max[p]=Math.max(Max[p*2], Max[p*2+1]);
      
    }
      
  }
  
  public static long query(int l,int r,int p,int cl,int cr) {
    
     if (cl> r || cr < l)
            return 0;
        else if (cl >= l && cr <= r)
            return Tree[p];
        else
        {
            int mid =cl+(cr-cl)/2;
            return query(l, r, p * 2, cl, mid) + query(l, r, p * 2 + 1, mid + 1, cr ); 
            // 上一行拆成三行写就和区间修改格式一致了
        }
  }
  
  public static int getMax(int l,int r,int p,int cl,int cr) {
    
    if(cl>r||l>cr) {
      return 0;
    }
    if(cl>=l&&cr<=r)
      return Max[p];
    
    int mid=cl+(cr-cl)/2;
    
    return Math.max(getMax(l,r,p*2,cl,mid),getMax(l,r,p*2+1,mid+1,cr));
  }
  
  
  
}

Python语言

n,m = map(int,input().split())
value = list(map(int,input().split()))
num = []
a = [ dict() for j in range(4*n)]
# print(a)
def update(k):
    node = a[k]
    node['sum'] = a[k * 2]['sum'] + a[k * 2 + 1]['sum']
    node['max'] = max(a[k * 2]['max'], a[k * 2 + 1]['max'])
def built(k,l,r):
    node = a[k]
    node['l'] = l
    node['r'] = r
    if l == r:
        node['sum'] = value[l]
        node['max'] = value[l]
    else:
        mod = int((r+l)/2)
        built(2*k,l,mod)
        built(2*k+1,mod+1,r)
        update(k)
def chang(k,x,y):
    node = a[k]
    if node['l']==node['r']:
        node['sum'] = y
        node['max'] = y
    else:
        mod = int((node['r']+node['l'])/2)
        if x>mod:
            chang(k*2+1,x,y)
        else:
            chang(k*2,x,y)
        update(k)
def Sum(k,l,r):
    node = a[k]
    if node['l']==l and node['r']==r:
        return node['sum']
    else:
        mod = int((node['r']+node['l'])/2)
        if r<=mod:
            return Sum(k*2,l,r)
        elif l>mod:
            return Sum(k*2+1,l,r)
        else:
            return Sum(k*2,l,mod)+Sum(k*2+1,mod+1,r)
def Max(k,l,r):
    node = a[k]
    if node['l'] == l and node['r'] == r:
        return node['max']
    else:
        mod = int((node['r'] + node['l']) / 2)
        if r <= mod:
            return Max(k * 2, l, r)
        elif l > mod:
            return Max(k * 2+1, l, r)
        else:
            return max(Max(k * 2, l, mod),Max(k * 2 + 1, mod + 1, r))
built(1,0,n-1)
for i in range(m):
    p,x,y = map(int,input().split())
    if p == 1:
        chang(1,x-1,y)
    if p == 2:
        s=Sum(1,x-1,y-1)
        num.append(s)
    if p == 3:
        m = Max(1,x-1,y-1)
        num.append(m)
for i in num:
    print(i)

没有什么不付出就能拿到的结果,我们都是在负重前行,最终结果与自身先天的脑力有一定的关系,但是还是有很大一部分看自己后天的努力,其实从报名到比赛也就5个月左右,真正刷题的事件也就2个月,2个月回忆一下你真正的认真刷过题吗,如果你真的用尽所有的精力去努力了,那么我相信你最终的成绩一定会让你满意的,加油。


相关文章
|
1月前
|
人工智能 算法 Java
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1005 数字游戏
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1005 数字游戏
65 0
|
20天前
|
算法 C语言
数据结构和算法学习记录——栈和队列习题-用队列实现栈、用栈实现队列(核心思路、解题过程、完整题解)二
数据结构和算法学习记录——栈和队列习题-用队列实现栈、用栈实现队列(核心思路、解题过程、完整题解)二
17 2
|
5天前
|
人工智能 算法 搜索推荐
蓝桥杯宝藏排序题目算法(冒泡、选择、插入)
以下是内容的摘要: 本文介绍了三种排序算法:冒泡排序、选择排序和插入排序。冒泡排序通过不断交换相邻的逆序元素逐步排序,最坏情况下需要 O(n^2) 次比较。选择排序在每轮中找到剩余部分的最小元素并放到已排序序列的末尾,同样具有 O(n^2) 时间复杂度。插入排序则是将每个元素插入到已排序序列的正确位置,时间复杂度也是 O(n^2),但空间复杂度为 O(1)。
|
1月前
|
存储 算法 Java
蓝桥杯递归算法
蓝桥杯中的递归算法涉及将问题分解为子问题,通过函数自身调用来求解。优点是简洁易懂,但效率低且可能引发栈溢出。示例包括:数组求和、数的阶乘、斐波那契数列及最大公约数计算,以及字符串翻转。代码展示了各种递归场景的Java实现,如`f3`计算数组和,`f`求阶乘,`f1`计算斐波那契数,`f2`找最大公约数,和`f1`字符串反转。
26 1
|
1月前
|
算法 安全
死锁相关知识点以及银行家算法(解题详细步骤)
死锁相关知识点以及银行家算法(解题详细步骤)
32 2
|
20天前
|
算法 C语言
数据结构和算法学习记录——栈和队列习题-用队列实现栈、用栈实现队列(核心思路、解题过程、完整题解)一
数据结构和算法学习记录——栈和队列习题-用队列实现栈、用栈实现队列(核心思路、解题过程、完整题解)一
18 0
|
1月前
|
算法 安全 定位技术
【刷题】备战蓝桥杯 — dfs 算法
dfs算法在数据较小的情况下可以使用。 一定一定要确定好终止条件,避免栈溢出。 相应做好回溯,保证每次的遍历都是不一样的选择,避免少结果。 针对题目进行对应细节处理,有能力的话可以进行剪枝优化!!!
27 0
|
1月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1007 印章
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1007 印章
36 0
|
1月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1006 拿金币
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1006 拿金币
35 0
|
1月前
|
人工智能 算法 Java
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-992 士兵杀敌(二)
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-992 士兵杀敌(二)
37 1