牛客小白月赛86 解题报告 | 珂学家 | 最大子数组和变体 + lazy线段树动态区间树

news2024/9/22 5:33:34

前言

在这里插入图片描述


整体评价

终于回归小白月赛的内核了,希望以后也继续保持,_.


A. 水盐平衡

思路: 模拟

题目保证没有浓度相等的情况

盐度 a/b, c/d 的比较关系

演变为 ad, bc 两者的大小关系

#include <bits/stdc++.h>

using namespace std;

int main() {
    int t;
    cin >> t;
    while (t-- > 0) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        if (a * d > b * c) {
            cout << "S" << endl;
        } else {
            cout << "Y" << endl;
        }
    }
    return 0;
}

B. 水平考试

思路: 位运算

s, t可以转化为二进制形态

s为t的一个子集,其实表示为

然后 s & t == s

或者 s | t == t

两者皆可

t = int(input())

def mask(s: str) -> int:
    r = 0
    for c in s:
        r |= 1 << (ord(c) - ord('A'))
    return r

for i in range(t):
    s, t = input(), input()
    a, b = mask(s), mask(t)
    if a & b == a:
        print (10)
    else:
        print (0)

C. 数组段数

思路: 分段编码

给每个区间一个递增的编号

然后 id(e) - id(s) + 1

方法二, 利用区间前缀和作差,时间复杂度可以少一个log

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.TreeMap;

public class Main {

    public static void main(String[] args) {
        AReader sc = new AReader();
        int n = sc.nextInt(), m = sc.nextInt();

        TreeMap<Integer, Integer> tree = new TreeMap<>();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        int segId = 0;
        int j = 0;
        while (j < n) {
            int k = j + 1;
            while (k < n && arr[k - 1] == arr[k]) {
                k++;
            }
            tree.put(j, segId++);
            j = k;
        }

        for (int i =0; i < m; i++) {
            int l = sc.nextInt() - 1, r = sc.nextInt() - 1;
            int res = tree.floorEntry(r).getValue() - tree.floorEntry(l).getValue() + 1;
            System.out.println(res);
        }

    }

    static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

//        public BigInteger nextBigInt() {
//            return new BigInteger(next());
//        }
        // 若需要nextDouble等方法,请自行调用Double.parseDouble包装
    }

}

D. 剪纸游戏

思路: 传统的3种方案

  • DFS
  • BFS
  • 并查集

这边借助BFS实现

通过统计矩形的(minX, minY) -> (maxX, maxY)

然后统计 (maxY - minY + 1) * (maxX - minX + 1) == 连通图的个数

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;

public class Main {

    static final int[][] dirs = new int[][] {
            {-1, 0}, {1, 0}, {0, -1}, {0, 1}
    };

    static boolean check(int y, int x, char[][] grid, boolean[][] vis) {
        int h = grid.length, w = grid[0].length;

        int minY = y, minX = x;
        int maxY = y, maxX = x;
        int cnt = 1;

        Deque<int[]> deq = new ArrayDeque<>();
        deq.offer(new int[] {y, x});
        vis[y][x] = true;

        while (!deq.isEmpty()) {
            int[] pos = deq.poll();
            for (int i = 0; i < dirs.length; i++) {
                int ty = pos[0] + dirs[i][0];
                int tx = pos[1] + dirs[i][1];
                if (ty >= 0 && ty < h && tx >= 0 && tx < w) {
                    if (grid[ty][tx] == '.' && !vis[ty][tx]) {
                        vis[ty][tx] = true;
                        deq.offer(new int[] {ty, tx});
                        cnt++;

                        minY = Math.min(minY, ty);
                        minX = Math.min(minX, tx);
                        maxY = Math.max(maxY, ty);
                        maxX = Math.max(maxX, tx);
                    }
                }
            }
        }

        return minY == y && minX == x && (maxX - minX + 1) * (maxY - minY + 1) == cnt;
    }

    public static void main(String[] args) {
        AReader sc = new AReader();

        int h = sc.nextInt(), w = sc.nextInt();
        char[][] grids = new char[h][];
        for (int i = 0; i < h; i++) {
            grids[i] = sc.next().toCharArray();
        }

        int res = 0;
        boolean[][] vis = new boolean[h][w];
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (grids[i][j] == '.' && !vis[i][j]) {
                    if (check(i, j, grids, vis)) {
                        res++;
                    }
                }
            }
        }
        System.out.println(res);

    }

    static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }

}

E. 可口蛋糕

思路: 双指针滑窗 + 最大子数组和变体

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) {
        AReader sc = new AReader();

        int n = sc.nextInt();
        long W = sc.nextLong();

        long[] wpre = new long[n + 1];
        long[] ws = new long[n];
        for (int i = 0; i < n; i++) {
            ws[i] = sc.nextInt();
            wpre[i + 1] = wpre[i] + ws[i];
        }

        long[] dpre = new long[n + 1];
        long[] ds = new long[n];
        for (int i = 0; i < n; i++) {
            ds[i] = sc.nextInt();
            dpre[i + 1] = dpre[i] + ds[i];
        }

        long res = Long.MIN_VALUE;
        long best = 0;
        int j = 0;

        for (int i = 0; i < n; i++) {
            while (j <= i && (wpre[i + 1] - wpre[j + 1]) >= W) {
                best = Math.max(best + ds[j], ds[j]);
                best = Math.max(0, best);
                j++;
            }

            if (j > 0) {
                res = Math.max(res, best + dpre[i + 1] - dpre[j]);
            }
        }
        System.out.println(res);
    }

    static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
    }

}

F. 可口蛋糕

思路: lazy线段树 + 珂朵莉树

lazy线段树用于维护 区间更新+点查询

珂朵莉树,则单纯的维护区间

当然这边用差分数组,可以简化lazy线段树(二阶树状数组)

对于区间更新,可以分为l, r+1的分裂和重新组织

这样的话,其分类讨论的情况就变少了。


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;

public class Main {

    public static void main(String[] args) {
        AReader sc = new AReader();

        int n = sc.nextInt(), q = sc.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        LazySegTree segTree = new LazySegTree(0, n - 1, arr);

        // 1. 预处理一下
        long acc = 0; // 当前最大的值
        TreeMap<Integer, Integer> tree = new TreeMap<>();
        int j = 0;
        while (j < n) {
            int k = j + 1;
            while (k < n && arr[k - 1] + 1 == arr[k]) {
                k++;
            }
            acc += (long)(k - j) * (k - j);
            tree.put(j, k - 1);
            j = k;
        }

        // 和区间相关的题
        for (int i = 0; i < q; i++) {
            int l = sc.nextInt() - 1, r = sc.nextInt() - 1;
            int d = sc.nextInt();

            if (d == 0) {
                System.out.println(acc);
            } else {
                Map.Entry<Integer, Integer> ent = tree.floorEntry(l);
                segTree.update(l, r, d);
                
                if (ent.getKey() == l) {
                    if (l > 0 && segTree.query(l - 1) + 1 == segTree.query(l)) {
                        Map.Entry<Integer, Integer> ev1 = tree.floorEntry(l - 1);

                        int d1 = ev1.getValue() - ev1.getKey() + 1;
                        int d2 = ent.getValue() - ent.getKey() + 1;
                        acc = acc - (long)d1 * d1 - (long)d2 * d2;
                        acc = acc + (long)(d1 + d2) * (d1 + d2);

                        tree.remove(ev1.getKey());
                        tree.remove(ent.getKey());
                        tree.put(ev1.getKey(), ent.getValue());
                    }
                } else {
                    int d1 = l - ent.getKey();
                    int d2 = ent.getValue() - l + 1;

                    int span = ent.getValue() - ent.getKey() + 1;

                    acc = acc - (long)span * span;
                    acc = acc + (long)d1 * d1 + (long)d2 * d2;

                    tree.remove(ent.getKey());
                    if (ent.getKey() < l) {
                        tree.put(ent.getKey(), l - 1);
                    }
                    tree.put(l, ent.getValue());
                }

                // *)
                Map.Entry<Integer, Integer> ent2 = tree.floorEntry(r);
                if (ent2.getValue() == r) {
                    if (r + 1 < n && segTree.query(r) + 1 == segTree.query(r + 1)) {
                        Map.Entry<Integer, Integer> ev1 = tree.floorEntry(r + 1);

                        int d1 = ent2.getValue() - ent2.getKey() + 1;
                        int d2 = ev1.getValue() - ev1.getKey() + 1;

                        acc = acc - (long)d1 * d1 - (long)d2 * d2;
                        acc = acc + (long)(d1 + d2) * (d1 + d2);

                        tree.remove(ev1.getKey());
                        tree.remove(ent2.getKey());
                        tree.put(ent2.getKey(), ev1.getValue());
                    }
                } else {
                    int d2 = ent2.getValue() - r;
                    int d1 = r - ent2.getKey() + 1;

                    int span = ent2.getValue() - ent2.getKey() + 1;

                    acc = acc - (long)span * span;
                    acc = acc + (long)d1 * d1 + (long)d2 * d2;

                    tree.put(ent2.getKey(), r);
                    if (ent2.getValue() > r) {
                        tree.put(r + 1, ent2.getValue());
                    }
                }
                System.out.println(acc);
            }
        }

    }

    static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

//        public BigInteger nextBigInt() {
//            return new BigInteger(next());
//        }
        // 若需要nextDouble等方法,请自行调用Double.parseDouble包装
    }


    static
    public class LazySegTree {

        private int l, r;
        LazySegTree left, right;
        long v;
        long change;

        public LazySegTree(int l, int r, int[] arr) {
            this.l = l;
            this.r = r;
            if (l == r) {
                this.v = arr[l];
            } else {
                int m = l + (r - l) / 2;
                this.left = new LazySegTree(l, m, arr);
                this.right = new LazySegTree(m + 1, r, arr);
            }
        }

        public void update(int ul, int ur, int delta) {
            if (isLeaf()) {
                this.change += delta;
                this.v += this.change;
                this.change = 0;
                return;
            }
            if (this.l >= ul && this.r <= ur) {
                this.change += delta;
                return;
            }
            pushDown();

            int m = l + (r - l) / 2;
            if (ur <= m) {
                this.left.update(ul, ur, delta);
            } else if (ul > m) {
                this.right.update(ul, ur, delta);
            } else {
                this.left.update(ul, m, delta);
                this.right.update(m + 1, ur, delta);
            }
            pushUp();
        }

        public long query(int p) {
            if (isLeaf()) {
                if (this.change != 0) {
                    this.v += this.change;
                    this.change = 0;
                }
                return this.v;
            }
            pushDown();
            int m = l + (r - l) / 2;
            if (p <= m) {
                return this.left.query(p);
            } else {
                return this.right.query(p);
            }
        }

        void pushDown() {
            if (this.change != 0) {
                if (this.left != null) this.left.change += this.change;
                if (this.right != null) this.right.change += this.change;
                this.change = 0;
            }
        }

        void pushUp() {
        }

        boolean isLeaf() {
            return this.l == this.r;
        }

    }

}

写在最后

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1398398.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【北京】买套二手房需要多少钱?

上次我们看了苏州和上海的二手房&#xff0c;这次我们一起来看下北京的二手房价格如何。 数据来源 数据来自贝壳二手房&#xff0c;每个区最多获取了3千条房源信息&#xff0c;数据共计4万条左右 对数据感兴趣的朋友&#xff0c;公众号后台发送北京二手房获取数据文件 各区房…

面试之Glide如何绑定Activity的生命周期

Glide绑定Activity生命周期 Glide.with() 下面都是它的重载方法&#xff0c;Context&#xff0c;Activity&#xff0c;FragmentActivity, Fragment, android.app.Fragment fragment,View都可以作为他的参数&#xff0c;内容大同小异&#xff0c;都是先getRetriever&#xff0…

【C++入门到精通】智能指针 shared_ptr 简介及C++模拟实现 [ C++入门 ]

阅读导航 引言一、简介二、成员函数三、使用示例四、C模拟实现五、std::shared_ptr的线程安全问题六、总结温馨提示 引言 在 C 动态内存管理中&#xff0c;除了 auto_ptr 和 unique_ptr 之外&#xff0c;还有一种智能指针 shared_ptr&#xff0c;它可以让多个指针共享同一个动…

关于大模型学习中遇到的3

来源&#xff1a;网络 Embedding模型 随着大型语言模型的发展&#xff0c;以ChatGPT为首&#xff0c;涌现了诸如ChatPDF、BingGPT、NotionAI等多种多样的应用。公众大量地将目光聚焦于生成模型的进展之快&#xff0c;却少有关注支撑许多大型语言模型应用落地的必不可少的Embed…

STM32407用汇顶的GT911触摸芯片调试实盘

这个配置很关键 代码 #include "stm32f4xx.h" #include "GT9147.h" #include "Touch.h" #include "C_Touch_I2C.h" #include "usart.h" #include "delay.h" #include "LCD.h" #incl…

HarmonyOS 页面跳转控制整个界面的转场动画

好 本文 我们来说 页面间的转场动画 就是 第一个界面到另一个界面 第一个界面的退场和第二个界面的进场效果 首先 我这里 创建了两个页面文件 Index.ets和AppView.ets index组件 编写代码如下 import router from "ohos.router" Entry Component struct Index {b…

视频监控需求记录

记录一下最近要做的需求&#xff0c;我个人任务还是稍微比较复杂的 需求&#xff1a;需要实现一个视频实时监控、视频回放、视频设备管理&#xff0c;以上都是与组织架构有关 大概的界面长这个样子 听着需求好像很简单&#xff0c;但是~我们需要在一个界面上显示两个厂商的视…

STM32标准库开发——串口发送/单字节接收

USART基本结构 串口发送信息 启动串口一的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);初始化对应串口一的时钟&#xff0c;引脚&#xff0c;将TX引脚设置为复用推挽输出。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_In…

我们应该了解的⽤户画像

当我们谈⽤户画像时&#xff0c;到底在谈什么 对于互联⽹公司来说&#xff0c;企业的增⻓、内容、活动、产品等⼯作基本上都是围绕着“⽤户”来做的&#xff0c;可以说都是在做“⽤户运营”这个⼯作&#xff0c;⽽⽤户画像是⽤户运营⼯作中⾮常重要的⼀环 ⽤户画像的主要特征是…

Linux命令手册

简介 Multics&#xff08;大而全&#xff09;项目失败&#xff0c;吸取教训启动Unix&#xff08;小而精&#xff09;&#xff0c;Linus Benedict Torvalds受Unix启发开发初始版本Linux内核&#xff0c;Git也由其开发&#xff0c;目的是为了更好的管理Linux内核开发。Unix是商业…

Windows如何部署TortoiseSVN客户端

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

专业130+总分380+哈尔滨工程大学810信号与系统考研经验水声电子信息与通信

今年专业课810信号与系统130&#xff0c;总分380顺利考上哈尔滨工程大学&#xff0c;一年的努力终于换来最后的录取&#xff0c;期中复习有得有失&#xff0c;以下总结一下自己的复习经历&#xff0c;希望对大家有帮助&#xff0c;天道酬勤&#xff0c;加油&#xff01;专业课&…

Java找二叉树的公共祖先

描述&#xff1a; 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节…

[AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言4.5key价格泄漏ChatGPT4.0使用地址ChatGPT正确打开方式最新功能语音助手存档…

【C语言】编译和链接深度剖析

文章目录 &#x1f4dd;前言&#x1f320; 翻译环境和运行环境&#x1f309;翻译环境 &#x1f320;预处理&#xff08;预编译&#xff09;&#x1f309;编译 &#x1f320;词法分析&#x1f320;语法分析 &#x1f309;语义分析&#x1f320;汇编 &#x1f309; 链接&#x1f…

动态闪图怎么在线合成?仅需三秒在线合成

GIF闪图是一种常见的动态图像格式&#xff0c;它由多个静态图像帧组成&#xff0c;以连续的方式播放&#xff0c;形成动画效果。每个图像帧都可以包含不同的颜色和透明度&#xff0c;因此GIF闪图通常用于展示简单的动画、表情符号或者短视频片段。这种格式在网络上广泛应用&…

论rtp协议的重要性

rtp ps流工具 rtp 协议&#xff0c;实时传输协议&#xff0c;为什么这么重要&#xff0c;可以这么说&#xff0c;几乎所有的标准协议都是国外创造的&#xff0c;感叹一下&#xff0c;例如rtsp协议&#xff0c;sip协议&#xff0c;webrtc&#xff0c;都是以rtp协议为基础&#…

C++中的static(静态)

2014年1月19日 内容整理自The Cherno:C系列 2014年1月20日 内容整理自《程序设计教程&#xff1a;用C语言编程 第三版》 陈家骏 郑滔 -----------------------------------------------------------------------------------------------------------------------------…

【RT-DETR有效改进】利用MobileNetV3替换Backbone(轻量化网络结构,提点)

前言 大家好&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持ResNet32、ResNet101和PP…

TEE2024大湾区进出口贸易博览会

TEE2024大湾区进出口贸易博览会 INTE 2024RNATIONAL TRADE E-COMMERCE EXPO 时间&#xff1a;2024年08月11--13日 地点&#xff1a;深圳福田会展中心 联合主办&#xff1a; 深圳市电子商务协会 深圳市跨境电子商务行业发展促进会 广东进出口商会 广东省国牌出海电子商务…