蓝桥杯官网 试题 PREV-278 历届真题 双向排序【第十二届】【省赛】【研究生组】【C++】【C】【Java】【Python】四种解法

简介: 蓝桥杯官网 试题 PREV-278 历届真题 双向排序【第十二届】【省赛】【研究生组】【C++】【C】【Java】【Python】四种解法

为帮助大家能在6月18日的比赛中有一个更好的成绩,我会将蓝桥杯官网上的历届决赛题目的四类语言题解都发出来。希望能对大家的成绩有所帮助。


今年的最大目标就是能为【一亿技术人】创造更高的价值。


资源限制


内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s


image.png


C++

#include<stdio.h>
#include<algorithm>
#define N 100010
#define x first
#define y second
using namespace std;
typedef pair<int,int> PIT;
PIT req[N];
int ans[N];
int main()
{
  int n,m;
  int i,j;
  int top;
  int p,q;
  int k,l,r;
  while(scanf("%d %d",&n,&m)==2)
  {
    top = 0;
    for(i=0;i<m;i++)
    {
      scanf("%d %d",&p,&q);
      if(!p) // 操作0
      {
        while(top && req[top].x == 0)   // 如果出现连续的0操作,则记录最大的操作范围 
              q = max(q,req[top--].y);
          while(top >= 2 && req[top-1].y <= q)  // 如果当前操作的范围比上一次的操作范围大,则把上一次的0和1操作删除
            top -= 2;
        req[++top] = {0,q};   // 保存最优的操作 
      } 
      else if(top)  //操作1 && 操作0已经进行过,因为第一个操作是1的话无意义
      {
        while(top && req[top].x == 1) //如果是连续的1操作,则记录最大的操作范围
            q = min(q,req[top--].y) ;   // 因为是给后缀排序,q越小,操作的范围越大
        while(top >= 2 && req[top-1].y >= q)  
            top -= 2;
        req[++top] = {1,q};
      } 
    }
    k = n;
    l = 1;
    r = n;
    for(i=1;i<=top;i++)
    {
      if(req[i].x == 0)  // 操作0
      {
        while(l <= r && r > req[i].y) 
            ans[r--] = k--;
      } 
      else   // 操作1 
      {
        while(l <= r && l < req[i].y)
            ans[l++] = k--;
      }
      if(l > r)  break;
    }
    if(top % 2) // 操作1
    {
      while(l <= r)
          ans[l++] = k--;
    } 
    else    // 操作0 
    {
      while(l <= r)
          ans[r--] = k--;
    }
    for(i=1;i<=n;i++)
    {
      printf("%d ",ans[i]);
    }
    printf("\n");
  }
  return 0;
}

C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define x first
#define y second
typedef struct{
  int x;
  int y;
}PII;
const int N = 100010;
int main()
{
  int n, m;
PII stk[N];
int ans[N];
  int i , j ;
    scanf("%d%d", &n, &m);
    int top = 0;
    while (m -- )
    {
        int p, q;
        scanf("%d%d", &p, &q);
        if (!p)//操作1 
        {
            while (top && stk[top].x == 0) 
    q = fmax(q, stk[top -- ].y);//出现连续的操作1,我们取最大 
            while (top >= 2 && stk[top - 1].y <= q) 
    //如果当前的操作1比上一次的操作1范围大,则将上一次操作1和操作2删除 
    top -= 2;
    PII num;
    num.x = 0;
    num.y = q;
            stk[ ++ top] = num;//存本次最佳操作 
        }
        else if (top)//操作2 &&且操作1已经进行过(操作二第一个用没效果) 
        {
            while (top && stk[top].x == 1) 
    q = fmin(q, stk[top -- ].y);
            while (top >= 2 && stk[top - 1].y >= q) 
    top -= 2;
    PII num;
    num.x = 1;
    num.y = q;
            stk[ ++ top] = num;
        }
    }
    int k = n, l = 1, r = n;
    for (i = 1; i <= top; i ++ )
    {
        if (stk[i].x == 0)//如果是操作1 
            while (r > stk[i].y && l <= r) ans[r -- ] = k -- ;//移动r值 ,并赋值 
        else
            while (l < stk[i].y && l <= r) ans[l ++ ] = k -- ; 
        if (l > r) break;
    }
    if (top % 2)
        while (l <= r) ans[l ++ ] = k -- ;
    else
        while (l <= r) ans[r -- ] = k -- ;
    for (i = 1; i <= n; i ++ )
        printf("%d ", ans[i]);
    return 0;
}


Java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main
{
  public static void main(String[]args) throws IOException{
  int n=in();
  int m=in();
  int[]sta=new int[m];
  int cnt=0;
  while(m-->0){
    int op=in();
    int mid=in();
    {//维护栈
    if(op==0){
      if(cnt%2!=op)//如果要放入的指令与栈中最后一个指令类型相同
      {
      if(cnt-1>=0&&sta[cnt-1]<=mid)cnt--;//则进行第一轮比较,如果当前更大则弹出最后一个
      else continue;//否则直接舍去当前指令,进入下一层循环
      }
      while(cnt-2>=0&&sta[cnt-2]<=mid) cnt-=2;//循环弹出
    }else{
      if(cnt%2!=op)//如果要放入的指令与栈中最后一个指令类型相同
      {
      if(cnt-1>=0&&sta[cnt-1]>=mid)cnt--;//则进行第一轮比较,如果当前更小则弹出最后一个
      else continue;//否则直接舍去当前指令,进入下一层循环
      }
      while(cnt-2>=0&&sta[cnt-2]>=mid) cnt-=2;//循环弹出
    }
    sta[cnt++]=mid;//压入栈
    }
  }
  int l=1;
  int r=n;
  int[] ans=new int[n+1];
  //x从大到小,从外到内填数字
  int x=n;
  for(int i=0;i<cnt;i++){
    int mid=sta[i];
    if(i%2==1){
    mid=Math.min(r, mid);
    while(l<mid)ans[l++]=x--;
    }
    else {
    mid=Math.max(l, mid);
    while(r>mid)ans[r--]=x--;
    }
    if(r-l<1)break;
  }
  if(l<=r)
    if(cnt%2==1) {
    while(l<=r)ans[l++]=x--;
    }else {
    while(l<=r)ans[r--]=x--;
    }
  out.print(ans[1]);
  for(int i=2;i<=n;i++) {
    out.print(" "+ans[i]);
  }
  out.println();
  out.flush();
  }
  static StreamTokenizer in=new StreamTokenizer (new BufferedReader(new InputStreamReader(System.in)));
  static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
  static int in() throws IOException{
  in.nextToken();
  return(int)in.nval;
  }
}


Python

# -*- coding: utf-8 -*-
read = lambda tp: map(tp, input().split())
def solve():
    n, m = read(int)
    ops = []
    for _ in range(m):
        p, q = read(int)
        if not p:
            while ops and ops[-1][0] == 0:
                q = max(ops.pop()[1], q)
            while len(ops) >= 2 and ops[-2][1] <= q:
                ops.pop(), ops.pop()
            ops.append([0, q])
        elif ops:
            while ops and ops[-1][0] == 1:
                q = min(ops.pop()[1], q)
            while len(ops) >= 2 and ops[-2][1] >= q:
                ops.pop(), ops.pop()
            ops.append([1, q])
    ans = [0] * (n + 1)
    k, l, r = n, 1, n
    for p, q in ops:
        if not p:
            while l <= r and r > q:
                ans[r] = k
                r -= 1
                k -= 1
        else:
            while l <= r and l < q:
                ans[l] = k
                l += 1
                k -= 1
        if l > r:
            break
    if len(ops) % 2:
        while l <= r:
            ans[l] = k
            l += 1
            k -= 1
    else:
        while l <= r:
            ans[r] = k
            r -= 1
            k -= 1
    print(*ans[1:], sep=' ')
if __name__ == '__main__':
    while True:
        try:
            solve()
        except EOFError:
            break
相关文章
|
4月前
|
Java 编译器 程序员
Java面试高频题:用最优解法算出2乘以8!
本文探讨了面试中一个看似简单的数学问题——如何高效计算2×8。从直接使用乘法、位运算优化、编译器优化、加法实现到大整数场景下的处理,全面解析了不同方法的原理和适用场景,帮助读者深入理解计算效率优化的重要性。
61 6
|
5月前
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
125 5
|
5月前
|
机器学习/深度学习 算法 关系型数据库
第十五届蓝桥杯C++B组省赛
第十五届蓝桥杯C++B组省赛
191 14
|
5月前
|
算法 测试技术 C++
【动态规划算法】蓝桥杯填充问题(C/C++)
【动态规划算法】蓝桥杯填充问题(C/C++)
|
5月前
|
人工智能 算法 BI
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
|
5月前
|
人工智能 C++
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
|
5天前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
55 23
|
12天前
|
Java 调度
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
81 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
|
16天前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
142 60
【Java并发】【线程池】带你从0-1入门线程池
|
1月前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
106 14

热门文章

最新文章