当前位置:   article > 正文

基础算法知识中篇(前缀和,差分,离散化,贪心)_前缀差分离散java

前缀差分离散java

前言

前缀和

在原先O(n)转换为O(1)时间内求区间和

前缀和算法模板 

  1. int []arr=new int[n];
  2. int []sum=new int[n+1];
  3. for(int i=1;i<=n;i++){
  4. sum[i]=sum[i-1]+arr[i-1];//sum[1]=arr[0] sum[n]=arr[0]+arr[1]+...arr[n-1]
  5. }

差分

对区间[l,r]加d

对差分做前缀和就可以还原原数组

差分可以将原序列上的区间操作转化为差分序列上的单点操作

差分数组的定义:diff[i]=a[i]-a[i-1];

对差分数组做前缀和可以还原原数组。

区间[l,r]加上d   diff[l]+=d 之后,对于diff以及a[]而言,从a[i]到a[n]都加上d

diff[r+1]-=d 相当于diff[r]之后以及数组a[]都没有发生改变

离散化

压缩值域(与线段树,树状数组结合起来)是一种辅助手段

对于依靠下标实现的算法而数据结构无法实现时,就需要考虑离散化。

离散化数组要求内部是有序(一般是去重的,当然也存在不需要去重的方法)

贪心算法

求解的问题分解成子问题,求得局部的最优解合成原来问题的一个解。(局部最优到全局最优)

编号1276小明的彩灯

题目描述

小明拥有 N 个彩灯,第 i 个彩灯的初始亮度为 ai​。

小明将进行 Q 次操作,每次操作可选择一段区间,并使区间内彩灯的亮度 +x(x 可能为负数)。

求 Q 次操作后每个彩灯的亮度(若彩灯亮度为负数则输出 0)。

输入描述

第一行包含两个正整数 N,Q,分别表示彩灯的数量和操作的次数。

第二行包含 N 个整数,表示彩灯的初始亮度。

接下来 Q 行每行包含一个操作,格式如下:

l r x,表示将区间 l∼r 的彩灯的亮度 +x。

1≤N,Q≤5×105,0≤ai​≤109,1≤l≤r≤N,−10^9≤x≤10^9

输出描述

输出共 11 行,包含 N 个整数,表示每个彩灯的亮度。

输入输出样例

示例 1

输入

  1. 5 3
  2. 2 2 2 1 5
  3. 1 3 3
  4. 4 5 5
  5. 1 1 -100

输出

0 5 5 6 10

 代码

 

  1. package lanqiaoyun;
  2. import java.util.*;
  3. public class a1276 {
  4. public static void main(String[] args) {
  5. // TODO Auto-generated method stub
  6. Scanner scan=new Scanner(System.in);
  7. int n=scan.nextInt();
  8. int q=scan.nextInt();
  9. long []arr=new long [n];
  10. long []diff=new long [n+1];
  11. for(int i=0;i<n;i++) {
  12. arr[i]=scan.nextLong();
  13. }
  14. while(q-->0) {
  15. int l=scan.nextInt()-1;
  16. int r=scan.nextInt()-1;
  17. int x=scan.nextInt();
  18. diff[l]+=x;
  19. diff[r+1]-=x;
  20. }//初次操作
  21. for(int i=1;i<arr.length;i++) {
  22. diff[i]+=diff[i-1];
  23. }//前缀和还原原数组
  24. for(int i=0;i<n;i++) {
  25. long c=arr[i]+diff[i];
  26. if(c<0) {
  27. System.out.print(0+" ");
  28. }else {
  29. System.out.print(c+" ");
  30. }
  31. }
  32. }
  33. }

                                  

编号180三体攻击

题目描述

三体人将对地球发起攻击。为了抵御攻击,地球人派出 A × B × C 艘战舰,在太空中排成一个 A 层 B 行 C 列的立方体。其中,第 i 层第 j 行第 k 列的战舰(记为战舰 (i, j, k))的生命值为d(i, j, k)。

三体人将会对地球发起 m 轮"立方体攻击",每次攻击会对一个小立方体中的所有战舰都造成相同的伤害。具体地,第 t 轮攻击用 7 个参数lat, rat, lbt, rbt, lct, rct, ht 描述;

所有满足 i ∈ [lat, rat],j ∈ [lbt, rbt],k ∈ [lct, rct] 的战舰 (i, j, k) 会受到ht 的伤害。如果一个战舰累计受到的总伤害超过其防御力,那么这个战舰会爆炸。

地球指挥官希望你能告诉他,第一艘爆炸的战舰是在哪一轮攻击后爆炸的。

输入描述

输入格式:

第一行包括 4 个正整数A, B, C, m;

第二行包含A × B × C 个整数,其中第((i − 1)×B + (j − 1)) × C + (k − 1)+1 个数为 d(i, j, k);

第 3 到第 m + 2 行中,第 (t − 2) 行包含 7 个正整数 lat, rat, lbt, rbt, lct, rct, ht。

其中A × B × C ≤ 10^6, m ≤ 10^6, 0 ≤ d(i, j, k), ht ≤ 10^9。

输出描述

输出第一个爆炸的战舰是在哪一轮攻击后爆炸的。保证一定存在这样的战舰。

输入输出样例

示例

输入

  1. 2 2 2 3
  2. 1 1 1 1 1 1 1 1
  3. 1 2 1 2 1 1 1
  4. 1 1 1 2 1 2 1
  5. 1 1 1 1 1 1 2

输出

2

代码                         

  1. package lanqiaoyun;
  2. import java.util.*;
  3. public class a3291 {
  4. public static void main(String[] args) {
  5. // TODO Auto-generated method stub
  6. Scanner scan=new Scanner(System.in);
  7. while(scan.hasNext()) {
  8. int n=scan.nextInt();
  9. int q=scan.nextInt();
  10. long []a=new long[n];
  11. for(int i=0;i<n;i++) {
  12. a[i]=scan.nextLong();
  13. }
  14. long []diff=new long[n+1];
  15. while(q-->0) {
  16. int x=scan.nextInt()-1;
  17. int y=scan.nextInt()-1;
  18. int z=scan.nextInt();
  19. diff[x]+=z;
  20. diff[y+1]-=z;
  21. }
  22. for(int i=1;i<n;i++) {
  23. diff[i]+=diff[i-1];
  24. }
  25. for(int i=0;i<n;i++) {
  26. long c=a[i]+diff[i];
  27. System.out.print(c+" ");
  28. }
  29. System.out.println(" ");
  30. }
  31. }
  32. }

编号 离散化

题目描述

 输入一个长度为n的数组An,输出第i个数在数组从小到大排序后的排名,数字大小相同排名一样。(n<=1e5,Ai<=1e9) 

输入

5

5 4 4 2 1

输出

4 3 3 2 1 

代码                                                                                                        

  1. package lanqiaoyun;
  2. import java.util.*;
  3. public class aaaaaaaaaa {
  4. public static void main(String[] args) {
  5. // TODO Auto-generated method stub
  6. Scanner scan=new Scanner(System.in);
  7. int n=scan.nextInt();
  8. long []a=new long [n];
  9. long []c=new long[n];
  10. List<Long> list =new ArrayList<>();
  11. for(int i=0;i<n;i++) {
  12. a[i]=scan.nextLong();
  13. if(!list.contains(a[i])) {
  14. list.add(a[i]);
  15. }
  16. }
  17. Arrays.sort(a);
  18. /*
  19. for(int i=0;i<n;i++) {
  20. System.out.print(a[i]+" ");
  21. }
  22. System.out.println(" ");
  23. for(long i:list) {
  24. System.out.print(i+" ");
  25. }
  26. System.out.println(" ");
  27. */
  28. long []cx=new long [n];
  29. for(Long i:list) {
  30. for(int j=0;j<n;j++) {
  31. if(i==a[j]) {
  32. cx[j]=list.indexOf(i)+1;
  33. }
  34. }
  35. }
  36. for(long x:cx) {
  37. System.out.print(x+" ");
  38. }
  39. }
  40. }

  1. package lanqiaoyun;
  2. import java.util.*;
  3. public class aaaaa {
  4. public static void main(String[] args) {
  5. // TODO Auto-generated method stub
  6. Scanner scan=new Scanner(System.in);
  7. int n=scan.nextInt();
  8. Integer[] arr1=new Integer [n];
  9. for(int i=0;i<n;i++) {
  10. arr1[i]=scan.nextInt();
  11. }
  12. Arrays.sort(arr1);
  13. Set<Integer> set=new HashSet<>();
  14. Map<Integer,Integer> map=new HashMap<>();
  15. for(int i=0;i<n;i++) {
  16. set.add(arr1[i]);
  17. map.put(arr1[i], set.size());
  18. }
  19. Arrays.sort(arr1,(o1,o2)->o2-o1);
  20. for(int i=0;i<n;i++) {
  21. System.out.print(map.get(arr1[i])+" ");
  22. }
  23. }
  24. }

 编号 2128重新排序

问题描述

给定一个数组 A 和一些查询 Li​,Ri​, 求数组中第Li​ 至第Ri​ 个元素之和。

小蓝觉得这个问题很无聊, 于是他想重新排列一下数组, 使得最终每个查 询结果的和尽可能地大。小蓝想知道相比原数组, 所有查询结果的总和最多可 以增加多少?

输入格式

输入第一行包含一个整数 n 。

第二行包含A1​,A2​,⋯,An​, 相邻两个整数之间用一个空格分隔。

第三行包含一个整数 m 表示查询的数目。

接下来 m 行, 每行包含两个整数Li​、Ri​, 相邻两个整数之间用一个空格分 隔。

输出格式

输出一行包含一个整数表示答案。

样例输入

  1. 5
  2. 1 2 3 4 5
  3. 2
  4. 1 3
  5. 2 5

样例输出

4

样例说明

原来的和为 6+14=206+14=20, 重新排列为 (1,4,5,2,3)(1,4,5,2,3) 后和为 10+14=2410+14=24, 增 加了 4。

代码

  1. package lanqiaoyun;
  2. import java.util.*;
  3. public class a2128 {
  4. public static void main(String[] args) {
  5. // TODO Auto-generated method stub
  6. Scanner scan=new Scanner(System.in);
  7. int n=scan.nextInt();
  8. int[] arr=new int[n];
  9. for(int i=0;i<n;i++) {
  10. arr[i]=scan.nextInt();
  11. }
  12. int m=scan.nextInt();
  13. int []d=new int[n];
  14. while(m-->0) {
  15. long l=scan.nextLong()-1;
  16. long r=scan.nextLong()-1;
  17. d[(int) l]+=1;
  18. if(l+r<n) {
  19. d[(int) (r+1)]-=1;
  20. }
  21. }
  22. for(int i=1;i<n;i++) {
  23. d[i]+=d[i-1];
  24. }
  25. long res=0;
  26. for(int i=0;i<n;i++) {
  27. res+=(long)arr[i]*d[i];
  28. }
  29. Arrays.sort(arr);
  30. Arrays.sort(d);
  31. long num=0;
  32. for(int i=0;i<n;i++) {
  33. num+=(long)arr[i]*d[i];
  34. }
  35. System.out.print(num-res);
  36. }
  37. }

编号545谈判

题目描述

在很久很久以前,有 n 个部落居住在平原上,依次编号为 11 到 n。第 i 个部落的人数为 ti​。

有一年发生了灾荒。年轻的政治家小蓝想要说服所有部落一同应对灾荒,他能通过谈判来说服部落进行联合。

每次谈判,小蓝只能邀请两个部落参加,花费的金币数量为两个部落的人数之和,谈判的效果是两个部落联合成一个部落(人数为原来两个部落的人数之和)。

输入描述

输入的第一行包含一个整数 n,表示部落的数量。

第二行包含 n 个正整数,依次表示每个部落的人数。

其中,1≤n≤1000,1≤ti​≤104。

输出描述

输出一个整数,表示最小花费。

输入输出样例

示例 1

输入

  1. 4
  2. 9 1 3 5

输出

31

代码 

  1. package lanqiaoyun;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.LinkedList;
  5. import java.util.List;
  6. import java.util.Queue;
  7. import java.util.Scanner;
  8. public class a545 {
  9. public static void main(String[] args) {
  10. // TODO Auto-generated method stub
  11. Scanner scan=new Scanner(System.in);
  12. int n=scan.nextInt();
  13. List<Integer> list=new ArrayList<>();
  14. //Queue<Integer> queue=new LinkedList<>();
  15. //int []a=new int [n+1];
  16. for(int i=0;i<n;i++) {
  17. int a=scan.nextInt();
  18. list.add(a);
  19. }
  20. /*for(int i=0;i<n;i++) {
  21. System.out.print(list.get(i)+" ");
  22. }*/
  23. int money=0;//金币
  24. int num=0;//人数
  25. while(list.size()>1) {
  26. Collections.sort(list);
  27. int a=list.get(0);
  28. int b=list.get(1);
  29. num=a+b;//不累加
  30. money=a+b+money;//累加
  31. list.remove(0);
  32. list.remove(0);
  33. list.add(num);
  34. }
  35. System.out.println(money);
  36. }
  37. }

编号1371回文判定(双指针)

题目描述

给定一个长度为 n 的字符串 S。请你判断字符串 S 是否回文。

输入描述

输入仅 11 行包含一个字符串 S。

1≤∣S∣≤106,保证 S 只包含大小写、字母。

输出描述

若字符串 S 为回文串,则输出 Y,否则输出 N。

输入输出样例

示例 1

输入

abcba

输出

Y

示例 2

输入

abcbb

输出

N

 代码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/871437
推荐阅读
相关标签
  

闽ICP备14008679号