2795Billboard segment_tree

本文深入探讨了C++模板元编程技术,重点介绍了如何利用STL库实现高效算法优化,旨在提升程序员对现代C++语言特性的理解和实践能力。
#include <iostream>
#include <cstdio>
#include <cstring>
#define lson l,m,rt<< 1
#define rson m+1,r,rt <<1 | 1
using namespace std;
const int N=2200100;
long long mx[N<<2];
int h,w;
//按序号来说,左边的小于右边的,而题中要求选尽量小的,左边优先权大于右边
void pushup(int rt){
    mx[rt] = max(mx[rt << 1],mx[rt << 1 | 1]);
}
void build(int l,int r,int rt){
    mx[rt]=w;
    if(l==r){
        return ;
    }
    int m=(l+r) >> 1;
    build(lson);
    build(rson);
    //pushup(rt);
}
int Query(int x,int l,int r,int rt){
    if(l==r){
        mx[rt]-=x;//use x;
        return l;//为什么返回l,而不是rt,因为rt表示子树的根,,而真正和层数相符的是[a,a],即l,根的更新比l,r慢一拍,进入下层递归,rt才更新
    }
    int m= (l+r)>>1;
    int ret=0;
    ret=(x>mx[rt<<1])?Query(x,rson):Query(x,lson);//mx[rt<<1]把位运算写反了...debug去吧= =
    pushup(rt);//////////因为rt变了
    return ret;
}
int main()
{
    int n,x;
    while(scanf("%d%d%d",&h,&w,&n)==3){
        h=(h>n)?n:h;//直接代会re= =
        build(1,h,1);//节点数的控制,1e9爆,而h>n无意义(后面的空行没用)
        while(n--){
            scanf("%d",&x);
            if(x>mx[1]){
                printf("-1\n");
            }else{
                printf("%d\n",Query(x,1,h,1));
            }
        }
    }
    return 0;
}

基于51单片机,实现对直流电机的调速、测速以及正反转控制。项目包含完整的仿真文件、源程序、原理图和PCB设计文件,适合学习和实践51单片机在电机控制方面的应用。 功能特点 调速控制:通过按键调整PWM占空比,实现电机的速度调节。 测速功能:采用霍尔传感器非接触式测速,实时显示电机转速。 正反转控制:通过按键切换电机的正转和反转状态。 LCD显示:使用LCD1602液晶显示屏,显示当前的转速和PWM占空比。 硬件组成 主控制器:STC89C51/52单片机(与AT89S51/52、AT89C51/52通用)。 测速传感器:霍尔传感器,用于非接触式测速。 显示模块:LCD1602液晶显示屏,显示转速和占空比。 电机驱动:采用双H桥电路,控制电机的正反转和调速。 软件设计 编程语言:C语言。 开发环境:Keil uVision。 仿真工具:Proteus。 使用说明 液晶屏显示: 第一行显示电机转速(单位:转/分)。 第二行显示PWM占空比(0~100%)。 按键功能: 1键:加速键,短按占空比加1,长按连续加。 2键:减速键,短按占空比减1,长按连续减。 3键:反转切换键,按下后电机反转。 4键:正转切换键,按下后电机正转。 5键:开始暂停键,按一下开始,再按一下暂停。 注意事项 磁铁和霍尔元件的距离应保持在2mm左右,过近可能会在电机转动时碰到霍尔元件,过远则可能导致霍尔元件无法检测到磁铁。 资源文件 仿真文件:Proteus仿真文件,用于模拟电机控制系统的运行。 源程序:Keil uVision项目文件,包含完整的C语言源代码。 原理图:电路设计原理图,详细展示了各模块的连接方式。 PCB设计:PCB布局文件,可用于实际电路板的制作。
这段代码的作用是将一个时间段(以秒为单位的时间,如开始时间和结束时间)格式化为特定字符串格式,并写入一个字符数组 `tmpstr` 中。 --- ### ✅ 代码解析: ```c snprintf(tmpstr, sizeof(tmpstr), "\"%d%d-%d%d:%d\"", segment_item->StartTime/60, segment_item->StartTime%60, segment_item->EndTime/60, segment_item->EndTime%60, segment_item->Type); ``` #### 参数说明: - `tmpstr`: 输出的目标缓冲区。 - `sizeof(tmpstr)`: 缓冲区大小,防止溢出。 - 格式字符串:`"%d%d-%d%d:%d"`,表示输出格式。 - 后续参数分别是: - `segment_item->StartTime / 60`:把秒数转换成分钟数的整数部分(小时)。 - `segment_item->StartTime % 60`:分钟数的余数部分(分钟)。 - `segment_item->EndTime / 60` - `segment_item->EndTime % 60` - `segment_item->Type`:某种类型值(比如记录模式、触发类型等) --- ### ✅ 示例: 假设: ```c segment_item->StartTime = 60 * 9 + 30; // 9:30 = 570 秒 segment_item->EndTime = 60 * 10 + 45; // 10:45 = 645 秒 segment_item->Type = 1; ``` 代入上面的表达式: - StartTime / 60 = 9 - StartTime % 60 = 30 - EndTime / 60 = 10 - EndTime % 60 = 45 - Type = 1 格式化后结果: ```text "930-1045:1" ``` ⚠️ **注意**:这里 `%d%d` 是拼接两个数字,不是补零格式化。所以 `9` 和 `30` 直接拼成了 `930`,而不是 `"0930"` 或 `"09:30"`。 --- ### ❗潜在问题: 这种写法会导致时间格式不统一,例如: | 时间 | 表示方式 | |------|----------| | 0:5 -> 05 分钟 | 会变成 `05` | | 10:5 -> 105 分钟 | 会变成 `105`,这与 1:05 混淆 | 因此,这个格式容易造成歧义,建议使用固定宽度格式化,例如: ```c snprintf(tmpstr, sizeof(tmpstr), "\"%02d%02d-%02d%02d:%d\"", segment_item->StartTime/60, segment_item->StartTime%60, segment_item->EndTime/60, segment_item->EndTime%60, segment_item->Type); ``` 这样对于 `9:30` 到 `10:45` 的输出就是: ```text "0930-1045:1" ``` 更清晰、无歧义。 --- ### ✅ 总结作用: 该段代码的作用是将一个时间区间(以秒为单位的起止时间)和一个类型值组合成如下格式的字符串: ``` "HHMM-HHMM:type" ``` 其中: - `HHMM` 是小时+分钟的拼接形式(未补零) - `type` 是某种类型标识 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值