ST表-龙骑士军团【算法赛】

龙骑士军团【算法赛】

问题描述

龙骑士军团是蓝桥王国战斗力最强的军团,该军团总共有 nn 位龙骑士,其中第 ii 位龙骑士的战斗力为 aiai​。

国王想考察一下军团长小蓝对于军团的掌控能力。具体来说,国王会提出 qq 个询问,每次询问给定四个整数 a,b,c,da,b,c,d,并要求小蓝从区间 a,ba,b 中选择一个点 LL,从区间 c,dc,d 中选择一个点 RR,使得 ∑i=LRai∑i=LR​ai​ 的值最大化。

这些问题难倒了小蓝。作为小蓝的助手,请你帮他解决这些问题。针对每个询问,你无需找出具体的 LL 和 RR,只需给出 ∑i=LRai∑i=LR​ai​ 的最大值即可。

输入格式

第一行输入两个整数 n,q(1≤n,q≤2×105)n,q(1≤n,q≤2×105),表示龙骑士数量和国王的询问数量。

第二行输入 nn 个整数 a1,a2,a3,⋯,an(−109≤ai≤109)a1​,a2​,a3​,⋯,an​(−109≤ai​≤109),依稀表示每位龙骑士的战斗力。

接下来 qq 行,每行四个整数 a,b,c,d(1≤a≤b<c≤d≤n)a,b,c,d(1≤a≤b<c≤d≤n),表示一次询问。

输出格式

输出 qq 行,每行一个整数表示答案。

样例输入

复制代码
8 3
-1 2 -3 4 -5 6 -7 8
1 2 3 4
1 1 2 2
1 3 5 8

样例输出

复制代码
3
1
5

样例说明

对于第一个查询,LL 我们可以选择 22,RR 选择 44,区间 2,42,4 的和为 33。

1.暴力版本(超时)

复制代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;


public class Main {

    static int N=2*100010;
    
    
    static int g[]=new int[N];
     static long s[]=new long[N];
    static int n;
    
    
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
    
    public static void main(String[] args) throws IOException { 
        StringTokenizer st=new StringTokenizer(br.readLine());
        n=Integer.parseInt(st.nextToken());
        int q=Integer.parseInt(st.nextToken());
        
        st=new StringTokenizer(br.readLine());
        
        for (int i = 1; i <= n; i++) {
        	g[i]=Integer.parseInt(st.nextToken());
        	s[i]=s[i-1]+g[i];
		}
       
        for (int i = 0; i < q; i++) {
        	st=new StringTokenizer(br.readLine());
        	int a=Integer.parseInt(st.nextToken()),b=Integer.parseInt(st.nextToken());
        	int c=Integer.parseInt(st.nextToken()),d=Integer.parseInt(st.nextToken());
        	long res=0;
        	int l=Math.max(a, b),r=Math.min(c, d);
        	res+=s[r]-s[l-1];
        	long left=0;
        	for (int j = Math.min(a, b); j < l; j++) {
				left=Math.max(left, s[l-1]-s[j-1]);
			}
        	res+=left;
        	long right=0;
        	for (int j = r+1; j <= Math.max(c,d); j++) {
				right=Math.max(right, s[j]-s[r]);
			}
        	res+=right;
        	bw.write(res+"\n");
		}
        
        
        br.close();
        bw.flush();
        bw.close();      
    }
   
}

2优化版本 ST表

复制代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;


public class Main {

    static int N=2*100010;
    
    
    static int g[]=new int[N];
    static long s[]=new long[N];//long 防止溢出
    static int log2[]=new int[N];
    static int n;
    
    
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
    
    public static void main(String[] args) throws IOException { 
        StringTokenizer st=new StringTokenizer(br.readLine());
        n=Integer.parseInt(st.nextToken());
        int q=Integer.parseInt(st.nextToken());
        
        st=new StringTokenizer(br.readLine());
        
        for (int i = 1; i <= n; i++) {
        	g[i]=Integer.parseInt(st.nextToken());
        	s[i]=s[i-1]+g[i];
		}
        log2[1]=0;
        for (int i = 2; i < N; i++) {
			log2[i]=log2[i>>1]+1;
		}
        //题目可以理解为s[j]-s[i]的最大值  i属于[a,b] j属于[c,d]
        //只需要使得s[j]最大 s[i]最小
        
        //构造ST表 倍增表  最大值
        long  f[][]=new long[n+1][log2[n]+1];
        for (int j = 0; j <= log2[n]; j++) {
			for (int i = 0; i+(1<<j)-1 <= n; i++) {//要从0开始 并且要保证右边界合法
				if(j==0)f[i][j]=s[i];
				else f[i][j]=Math.max(f[i][j-1],f[i+(1<<+(j-1))][j-1]);				
			}
		}
       //构造ST表 倍增表  最小值
        long  f1[][]=new long[n+1][log2[n]+1];
        for (int j = 0; j <= log2[n]; j++) {
			for (int i = 0; i+(1<<j)-1 <= n; i++) {
				if(j==0)f1[i][j]=s[i];
				else f1[i][j]=Math.min(f1[i][j-1], f1[i+(1<<+(j-1))][j-1]);				
			}
		}
        
        for (int i = 0; i < q; i++) {
        	st=new StringTokenizer(br.readLine());
        	int a=Integer.parseInt(st.nextToken()),b=Integer.parseInt(st.nextToken());
        	int c=Integer.parseInt(st.nextToken()),d=Integer.parseInt(st.nextToken());
        	//找到a-1到b-1中的最小s值
        	int k=log2[b-a+1];
        	long left=Math.min(f1[a-1][k],f1[b-1-(1<<k)+1][k]);
        	//找到c到d中的最大s值
        	int kk=log2[d-c+1];
        	long right=Math.max(f[c][kk],f[d-(1<<kk)+1][kk]);
        	bw.write((right-left)+"\n" );
		}
        
        
        br.close();
        bw.flush();
        bw.close();      
    }
   
}
相关推荐
大熊背4 小时前
树莓派相机自动白平衡详解(四)
算法·树莓派·白平衡·isppipeline
一米阳光86614 小时前
软考(中级)软件设计师核心笔记(9)算法——背包问题
笔记·算法·职场发展·软考·软件设计师·中级职称
晚风醉蝶4 小时前
1-11-奇偶排序-OddEvenSort
java·数据结构·算法
旖旎夜光5 小时前
LeetCode 852:山脉数组的峰顶索引(二分查找) —— 题解
数据结构·c++·算法·leetcode·二分查找
小雪崩6 小时前
嵌入式学习 day25:哈希表及排序与查找
linux·c语言·数据结构·学习·排序算法
白露与泡影6 小时前
解密 Pi 的 Harness 工程:Agent 会话如何实现持久化与恢复
java·人工智能·算法
happyprince8 小时前
01-整体观-Codex全貌解读(源码)
算法·ai编程
俊基科技8 小时前
别自己写算法了,让这颗37.5毫米的模组替你“闭嘴干活”
神经网络·算法·硬件开发·ai降噪·语音模块·回音消除
_Narcissus_9 小时前
动态规划初探(含完整代码实现)
c语言·数据结构·c++·算法·动态规划·背包问题·最短路径