当前位置: 首页 > article >正文

习题解答 | 一维差分与等差数列差分

一,航班预订统计

这里有 n 个航班,它们分别从 1 到 n 进行编号。

有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。

请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。

示例 1:

输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
输出:[10,55,45,25,25]
解释:
航班编号        1   2   3   4   5
预订记录 1 :   10  10
预订记录 2 :       20  20
预订记录 3 :       25  25  25  25
总座位数:      10  55  45  25  25
因此,answer = [10,55,45,25,25]

示例 2:

输入:bookings = [[1,2,10],[2,2,15]], n = 2
输出:[10,25]
解释:
航班编号        1   2
预订记录 1 :   10  10
预订记录 2 :       15
总座位数:      10  25
因此,answer = [10,25]

提示:

  • 1 <= n <= 2 * 104
  • 1 <= bookings.length <= 2 * 104
  • bookings[i].length == 3
  • 1 <= firsti <= lasti <= n
  • 1 <= seatsi <= 104
import java.util.Arrays;

public class Main{
	/*
	 * 这里有 n 个航班,它们分别从 1 到 n 进行编号。

有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。

请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。
	 * 
	 * */
	
	public void diff(int[] diff,int l,int r,int c) {
		diff[l] += c;
		diff[r+1] -=c;
	}
	public int[] corpFlightBookings(int[][] bookings, int n) {
		int[] arr = new int[n];
		int[] diff = new int[n+2];
		for (int[] book : bookings) {
			diff(diff,book[0],book[1],book[2]);
		}
		for(int i = 1;i < diff.length;i++) {
			diff[i] += diff[i-1];
		}
        arr = Arrays.copyOfRange(diff, 1, n+1);
        return arr;
    }
	

}

二,三步必杀

N个柱子排成一排,一开始每个柱子损伤度为0。

接下来勇仪会进行M次攻击,每次攻击可以用4个参数l,r,s,e来描述:

表示这次攻击作用范围为第l个到第r个之间所有的柱子(包含l,r),对第一个柱子的伤害为s,对最后一个柱子的伤害为e。

攻击产生的伤害值是一个等差数列。若l=1,r=5,s=2,e=10,则对第1~5个柱子分别产生2,4,6,8,10的伤害。

鬼族们需要的是所有攻击完成之后每个柱子的损伤度。

输入格式

第一行2个整数N,M,用空格隔开,下同。

接下来M行,每行4个整数l,r,s,e,含义见题目描述。

数据保证对每个柱子产生的每次伤害值都是整数。

输出格式

由于输出数据可能过大无法全部输出,为了确保你真的能维护所有柱子的损伤度,只要输出它们的异或和与最大值即可。

(异或和就是所有数字按位异或起来的值)

(异或运算符在c++里为^)

输入输出样例

输入 #1复制

5 2
1 5 2 10
2 4 1 1

输出 #1复制

3 10

输入 #2复制

6 2
1 5 2 10
2 4 1 1

输出 #2复制

3 10

说明/提示

样例解释:

样例1:

第一次攻击产生的伤害:2 4 6 8 10

第二次攻击产生的伤害:0 1 1 1 0

所有攻击结束后每个柱子的损伤程度:2 5 7 9 10。

输出异或和与最大值,就是3 10。

样例2:

没有打到第六根柱子,答案不变

数据范围:

本题满分为100分,下面是4个子任务。(x/y)表示(得分/测试点数量)

妖精级(18/3):1⩽n,m⩽1000。这种工作即使像妖精一样玩玩闹闹也能完成吧?

河童级(10/1):s=e,这可以代替我工作吗?

天狗级(20/4):1⩽n⩽105,1⩽m⩽105。小打小闹不再可行了呢。

鬼神级(52/2):没有特殊限制。要真正开始思考了。

以上四部分数据不相交。

对于全部的数据:1⩽n⩽107,1⩽m⩽3×105,1⩽l<r⩽n.

所有输入输出数据以及柱子受损伤程度始终在[0,9×1018]范围内。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Main{
	public static void set(long[] diff,int l,int r,int a,int b,int d) {
		diff[l] += a;
		diff[l+1] += d-a;
		diff[r+1] -= b+d;
		diff[r+2] += b;
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StreamTokenizer in = new StreamTokenizer(br);
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		
		while(in.nextToken() != StreamTokenizer.TT_EOF) {
			int n = (int)in.nval;
			in.nextToken();
			int m = (int)in.nval;
			long[] diff = new long[n+3];
			for(int i = 0;i < m;i++) {
				in.nextToken(); int l = (int)in.nval;
				in.nextToken(); int r = (int)in.nval;
				in.nextToken(); int a = (int)in.nval;
				in.nextToken(); int b = (int)in.nval;
				set(diff,l,r,a,b,(b-a)/(r-l));
			}
			for(int i =1;i < diff.length;i++) {
				diff[i] += diff[i-1];
			}
			
			for(int i =1;i < diff.length;i++) {
				diff[i] += diff[i-1];
				
			}
			long max = 0;
			long eo = 0;
			for(int i=1;i <= n;i++) {
				max = Math.max(max, diff[i]);
				eo ^= diff[i];
			}
			out.println(eo + " " + max);
		}
		out.flush();
		out.close();
		br.close();
	}
	
}

三,Lycanthropy

我们把山顶上的湖泊看作一条长度为 m 的直线,一开始水深都在水平线上,我们视作此时的水深为 '0'

接下来,在一瞬间,小正方形的"朋友"们跳起并扎入水中,导致在入水点的水降低而远离入水点的水升高,注意两个 "朋友" 可能在同一地点入水。

小正方形的每个朋友有一个体积数值 v,当体积为 v 的一个朋友跳入水中,我们设入水点为 i,将会导致 i−v+1 到 i 的水位依次降低 1,2,⋯,v

同样地,第 i 到 i+v−1 的水位会依次降低 v,v−1,⋯,1.

相对应地,i−v 的水位不变, i−v−1 到 i−2∗v 水位依次增加 1,2,⋯,v, i−2∗v 到 i−3∗v+1 水位依次增加 v,v−1,⋯,1

同样,i+v 水位不变,i+v+1 到 i+2∗v 水位增加 1,2,⋯,v,i+2∗v 到 i+3∗v−1 水位依次增加 v,v−1,⋯,1

现在小正方形想要穿过这个湖,他想要知道在这 n 个"朋友"跳入水中后湖上每个节点的水位,你能帮帮它吗?

输入格式

第一行为两个整数 n,m,表示"朋友"的数目与湖泊的宽度。

接下来 n 行,一行两个整数 v,x,表示第 i+1 个朋友的体积与入水点。

输出格式

一行 m 个整数,第 i 个整数表示 i 号位的水深。

输入输出样例

输入 #1复制

1 10
1 5

输出 #1复制

0 0 1 0 -1 0 1 0 0 0 

输入 #2复制

2 10
2 6
3 1

输出 #2复制

-2 0 0 0 0 0 2 2 2 2

说明/提示

对于 30% 的数据,n<=50,m<=500

对于 70% 的数据,n<=105,m<=105

对于 100% 的数据,n<=106,m<=106,1<=v<=10000,1<=x<=m

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Main{

	public static int MAXN = 1000001;
	public static int OFFSET = 30001;
	public static int[] arr = new int[OFFSET + MAXN + OFFSET];
	public static int n, m;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StreamTokenizer in = new StreamTokenizer(br);
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		while (in.nextToken() != StreamTokenizer.TT_EOF) {
			n = (int) in.nval;
			in.nextToken();
			m = (int) in.nval;
			for (int i = 0, v, x; i < n; i++) {
				in.nextToken(); v = (int) in.nval;
				in.nextToken(); x = (int) in.nval;
				fall(v, x);
			}
			build();
			int start = OFFSET + 1;
			out.print(arr[start++]);
			for (int i = 2; i <= m; i++) {
				out.print(" " + arr[start++]);
			}
			out.println();
		}
		out.flush();
		out.close();
		br.close();
	}
	public static void fall(int v, int x) {
		set(x - 3 * v + 1, x - 2 * v, 1, v, 1);
		set(x - 2 * v + 1, x, v - 1, -v, -1);
		set(x + 1, x + 2 * v, -v + 1, v, 1);
		set(x + 2 * v + 1, x + 3 * v - 1, v - 1, 1, -1);
	}
	public static void set(int l, int r, int s, int e, int d) {
		arr[l + OFFSET] += s;
		arr[l + 1 + OFFSET] += d - s;
		arr[r + 1 + OFFSET] -= d + e;
		arr[r + 2 + OFFSET] += e;
	}
	public static void build() {
		for (int i = 1; i <= m + OFFSET; i++) {
			arr[i] += arr[i - 1];
		}
		for (int i = 1; i <= m + OFFSET; i++) {
			arr[i] += arr[i - 1];
		}
	}

}


http://www.kler.cn/a/558950.html

相关文章:

  • 如何通过 Docker 在没有域名的情况下快速上线客服系统
  • Unity for Python —— 强大的 Python 脚本支持提升 Unity 编辑器效率
  • C语言递归——青蛙跳台阶问题和汉诺塔问题
  • 辗转相除法(欧几里得算法)
  • transformer架构嵌入层位置编码之RoPE旋转位置编码及简单实现示例
  • go-zero学习笔记(五)
  • Windows系统第一次运行C语言程序,环境配置,软件安装等遇到的坑及解决方法
  • 嵌入式之内存管理
  • 【2025.2最新版】从零开始的HTML网页开发学习笔记(包含网页基础概念 HTML语法 前端工具VsCode介绍)
  • mysql之B+ 树索引 (InnoDB 存储引擎)机制
  • 反射和注解
  • 自制操作系统前置知识汇编学习
  • 实验-安装Proteus
  • ZLMediaKi集群设置
  • 简说spring 的设计模式
  • Python项目源码33:待办事项列表应用2.0(命令行界面+Json+类)
  • Java基础常见的面试题(易错!!)
  • QT闲记-状态栏,模态对话框,非模态对话框
  • 485. 最大连续 1 的个数
  • 【CI/CD】Jenkinsfile管理+参数化构建+邮件通知以及Jenkins + SonarQube 代码审查