分布式队列 - 蓝桥杯2024年第十五届省赛真题

基础知识要求:

Java:方法、集合、泛型、数组、for循环、switch case语句、逻辑运算符、if判断、权限修饰符、static关键字、Scanner类

Python: 方法、列表、for循环、逻辑运算符、if判断、input()

题目: 

小蓝最近学习了一种神奇的队列:分布式队列。简单来说,分布式队列包含 N 个节点(编号为 0 至 N − 1,其中 0 号为主节点),其中只有一个主节点,其余为副节点。主/副节点中都各自维护着一个队列,当往分布式队列中添加元素时都是由主节点完成的(每次都会添加元素到队列尾部);副节点只负责同步主节点中的队列。可以认为主/副节点中的队列是一个长度无限的一维数组,下标为 0, 1, 2, 3 . . . ,同时副节点中的元素的同步顺序和主节点中的元素添加顺序保持一致。

由于副本的同步速度各异,因此为了保障数据的一致性,元素添加到主节点后,需要同步到所有的副节点后,才具有可见性。

给出一个分布式队列的运行状态,所有的操作都按输入顺序执行。你需要回答在某个时刻,队列中有多少个元素具有可见性。

输入格式

第一行包含一个整数 N,表示节点个数。接下来包含多行输入,每一行包含一个操作,操作类型共有以下三种:add、sync 和 query,各自的输入格式如下:

1. add element:表示这是一个添加操作,将元素 element 添加到队列中;

2. sync follower_id:表示这是一个同步操作,follower_id 号副节点会从主节点中同步下一个自己缺失的元素;

3. query:查询操作,询问当前分布式队列中有多少个元素具有可见性。

输出格式

对于每一个 query 操作,输出一行,包含一个整数表示答案。

样例输入

3
add 1
add 2
query
add 1
sync 1
sync 1
sync 2
query
sync 1
query
sync 2
sync 2
sync 1
query

样例输出

0
1
1
3

【样例说明】

执行到第一个 query 时,队列内容如下:

0:[1,2]
1:[]
2:[]
两个副节点中都无元素,因此答案为 0。
执行到第二个 query 时,队列内容如下:
0:[1,2,1]

1:[1,2]

2:[1]

只有下标为 0 的元素被所有节点同步,因此答案为 1。执行到第三个 query 时,队列内容如下:0:[1,2,1]1:[1,2,1]2:[1]

只有下标为 0 的元素被所有节点同步,因此答案为 1。执行到第四个 query 时,队列内容如下:0:[1,2,1]1:[1,2,1]2:[1,2,1]

三个元素都被所有节点同步,因此答案为 3。

【评测用例规模与约定】

对于 30% 的评测用例:1 ≤ 输入的操作数 ≤ 100。

对于 100% 的评测用例:1 ≤ 输入的操作数 ≤ 2000,1 ≤ N ≤ 10,1 ≤f ollower_id < N,0 ≤ element ≤ 105。

思路解析:

为了解决这个问题,我们可以使用一个数组来跟踪每个副节点当前同步到的队列位置。同时,我们需要记录主节点队列的当前长度。对于每一个操作,我们可以根据操作类型来更新这些信息。

Java代码示例:

import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
  
public class NodeSync {  
  
    public static void main(String[] args) {  
        Scanner scanner = new Scanner(System.in);  
        System.out.print("请输入节点总数(包括主节点和副节点):");  
        int N = scanner.nextInt();  
  
        List<Integer> mainQueue = new ArrayList<>(); // 主节点队列  
        int[] followerSync = new int[N - 1]; // 跟踪每个副节点同步到的位置(不包括主节点)  
  
        List<String> operations = new ArrayList<>();  
        // 这里假设operations已经以某种方式填充了  
        // operations.add("add 1");  
        // operations.add("add 2");  
        // ...  
  
        // 示例操作,硬编码到程序中  
        operations.add("add 1");  
        operations.add("add 2");  
        operations.add("query");  
        operations.add("add 1");  
        operations.add("sync 1");  
        operations.add("sync 1");  
        operations.add("sync 2");  
        operations.add("query");  
        operations.add("sync 1");  
        operations.add("query");  
        operations.add("sync 2");  
        operations.add("sync 2");  
        operations.add("sync 1");  
        operations.add("query");  
  
        processOperations(operations, N, mainQueue, followerSync);  
  
        scanner.close();  
    }  
  
    private static void processOperations(List<String> operations, int N, List<Integer> mainQueue, int[] followerSync) {  
        for (String operation : operations) {  
            String[] parts = operation.split(" ");  
            String op = parts[0];  
  
            switch (op) {  
                case "add":  
                    int element = Integer.parseInt(parts[1]);  
                    addElement(mainQueue, element);  
                    break;  
                case "sync":  
                    int followerId = Integer.parseInt(parts[1]);  
                    syncFollower(followerId, N, mainQueue, followerSync);  
                    break;  
                case "query":  
                    System.out.println(queryVisibility(mainQueue, followerSync));  
                    break;  
                default:  
                    System.out.println("无效的操作:" + op);  
            }  
        }  
    }  
  
    private static void addElement(List<Integer> mainQueue, int element) {  
        mainQueue.add(element);  
    }  
  
    private static void syncFollower(int followerId, int N, List<Integer> mainQueue, int[] followerSync) {  
        if (followerId >= 0 && followerId < N - 1 && followerSync[followerId] < mainQueue.size()) {  
            followerSync[followerId]++;  
        }  
    }  
  
    private static int queryVisibility(List<Integer> mainQueue, int[] followerSync) {  
        int minSync = Integer.MAX_VALUE;  
        for (int sync : followerSync) {  
            minSync = Math.min(minSync, sync);  
        }  
        return Math.min(minSync, mainQueue.size());  
    }  
}

Python代码示例:

def process_operations(operations, N):  
    main_queue = []  # 主节点队列  
    follower_sync = [0] * (N - 1)  # 跟踪每个副节点同步到的位置(不包括主节点)  
  
    def add_element(element):  
        main_queue.append(element)  
  
    def sync_follower(follower_id):  
        if 0 <= follower_id < N - 1 and follower_sync[follower_id] < len(main_queue):  
            follower_sync[follower_id] += 1  
  
    def query_visibility():  
        # 查找所有副节点中最小的同步位置  
        min_sync = min(follower_sync)  
        # 具有可见性的元素是主节点队列中从下标0到min_sync-1的元素  
        return min(min_sync, len(main_queue))  
  
    for operation in operations:  
        op, *args = operation.split()  
        if op == 'add':  
            element = int(args[0])  
            add_element(element)  
        elif op == 'sync':  
            follower_id = int(args[0])  
            sync_follower(follower_id)  
        elif op == 'query':  
            print(query_visibility())  
  
# 从用户输入中获取N的值  
N = int(input("请输入节点总数(包括主节点和副节点):"))  
  
# 假设operations是从某个输入源读取的,这里用字符串列表代替  
operations = [  
    "add 1",  
    "add 2",  
    "query",  
    "add 1",  
    "sync 1",  
    "sync 1",  
    "sync 2",  
    "query",  
    "sync 1",  
    "query",  
    "sync 2",  
    "sync 2",  
    "sync 1",  
    "query"  
]  
  
# 调用函数处理操作  
process_operations(operations, N)

  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千小凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值