CF286D 扫描线+STL

本文介绍了一种使用线段树进行优化的算法实践过程,通过对线段进行离散化处理,预先计算出通过和不通过的时间边界,再按时间顺序进行扫描。文章通过具体的AC代码展示了如何利用自定义结构体提高排序效率。

看到题目很容易想到用线段树写,不过为了挑战一下自己的思维,看了别人的代码,纠结的将思路理清楚了,磨蹭了一天才搞定。


首先将线段离散化,求出每个预处理的线段的刚好通过和刚好通不过的时间边界,最后按时间顺序扫描。


ps:用结构体内部排序比外部排序开了将近3倍。


ACcode:

#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int NS=100010;

struct Node
{
    int d,t,f;
    Node() {}
    Node(int a,int b,int c): d(a),t(b),f(c){}
    bool operator < (const Node cmp) const{
        return d<cmp.d;
    }
}L[NS<<1];

struct NOde
{
    int d,t,f;
    NOde() {}
    NOde(int a,int b,int c): d(a),t(b),f(c){}
    bool operator < (const NOde cmp) const{
        return t<cmp.t;
    }
}X[NS<<2];

int n,m,l,r,d,f,t,p,top,ans,cnt;
multiset<int> myset;

bool cmp1(Node a1,Node a2)
{
    if (a1.d!=a2.d) return a1.d<a2.d;
    return a1.f>a2.f;
}

bool cmp2(Node a1,Node a2)
{
    if (a1.t!=a2.t) return a1.t<a2.t;
    return a1.f>a2.f;
}

int main()
{
    while (~scanf("%d%d",&n,&m))
    {
        top=0;
        for (int i=0;i<m;i++)
        {
            scanf("%d%d%d",&l,&r,&t);
            L[i+i]=Node(l,t,1);
            L[i+i+1]=Node(r,t,-1);
        }
        m=m+m;
        sort(L,L+m);
        for (int i=0;i<m;i++)
        {
            d=L[i].d,t=L[i].t,f=L[i].f;
            if (!myset.empty())
            {
                X[top++]=NOde(l,*myset.begin()-p,1);
                X[top++]=NOde(r,*myset.begin()-d,-1);
            }
            p=d;
            if (f>0) myset.insert(t);
            else myset.erase(myset.find(t));
        }
        sort(X,X+top);
        ans=cnt=0;
        for (int i=0,j=0;i<n;i++)
        {
            scanf("%d",&t);
            for (;j<top&&X[j].t<=t;j++)
            {
                if (X[j].f<0)
                {
                    cnt++;
                    ans-=X[j].t;
                }
                else
                {
                    cnt--;
                    ans+=X[j].t;
                }
            }
            printf("%d\n",ans+t*cnt);
        }
    }
    return 0;
}


#include <stdio.h> #include <stdlib.h> #include <time.h> #include <stdbool.h> // ====================== // 全局变量 // ====================== float alarm_high = 30.0; // 高温阈值 float alarm_low = 10.0; // 低温阈值 bool is_fahrenheit = 0; // 温度单位标志(0:℃,1:℉) // 星期数组(索引0-6对应周日-周六) const char* weekdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // 时间结构体 typedef struct { int second; int minute; int hour; int date; int month; int weekday; // 0-6对应周日-周六 int year; // 0-99(实际年份=2000+year) } TIME; // ====================== // 函数声明 // ====================== // 延时函数 void delay_ms(unsigned int ms); // 报警函数 void check_alarm(float temp); // 显示函数 void display_time(void); void display_temp(float temp, bool is_fahrenheit); // 按键处理函数 char get_key(void); void key_handle(void); // 设置函数 void set_alarm_range(void); void set_time(void); void save_settings(void); // 模拟硬件函数 float simulate_temperature(void); TIME get_current_time(void); // ====================== // 主函数 // ====================== int main(void) { float temperature; // 初始化随机数种子 srand(time(NULL)); while(1) { // 模拟读取温度 temperature = simulate_temperature(); // 温度报警检测 check_alarm(temperature); // 显示时间和温度 display_time(); display_temp(temperature, is_fahrenheit); // 按键处理 key_handle(); // 延时避免资源占用过高 delay_ms(1000); } return 0; } // ====================== // 模拟温度传感器函数 // ====================== float simulate_temperature(void) { // 模拟20-30度之间的温度波动 static float base_temp = 25.0; float fluctuation = ((float)rand() / RAND_MAX) * 2.0 - 1.0; // -1到1度的随机波动 base_temp += fluctuation * 0.1; // 确保温度在合理范围内 if (base_temp < 15.0) base_temp = 15.0; if (base_temp > 35.0) base_temp = 35.0; return base_temp; } // ====================== // 获取模拟时间函数 // ====================== TIME get_current_time(void) { TIME t; time_t now = time(NULL); struct tm *tm_info = localtime(&now); t.second = tm_info->tm_sec; t.minute = tm_info->tm_min; t.hour = tm_info->tm_hour; t.date = tm_info->tm_mday; t.month = tm_info->tm_mon + 1; t.weekday = tm_info->tm_wday; t.year = tm_info->tm_year + 1900 - 2000; // 转换为2000+year格式 return t; } // ====================== // 报警函数 // ====================== void check_alarm(float temp) { if(temp > alarm_high || temp < alarm_low) { printf("\a"); // 发出警报声 printf("警告: 温度超出范围!\n"); } } // ====================== // 显示函数 // ====================== void display_time(void) { TIME t = get_current_time(); // 格式:2025-06-07 Sat 12:30:45 printf("\r%04d-%02d-%02d %s %02d:%02d:%02d ", 2000 + t.year, t.month, t.date, weekdays[t.weekday], t.hour, t.minute, t.second); } void display_temp(float temp, bool is_fahrenheit) { char unit = 'C'; if(is_fahrenheit) { temp = temp * 9.0/5.0 + 32.0; // 转换为华氏度 unit = 'F'; } // 格式:25.5°C printf("温度: %4.1f%c%c", temp, 0xDF, unit); // 显示阈值 printf(" 阈值: %.1f-%.1f%c", alarm_low, alarm_high, unit); // 显示单位切换提示 printf(" [A:切换单位]"); } // ====================== // 按键处理函数 // ====================== char get_key(void) { // 在沙盒环境中无法真正检测按键,这里简化处理 // 实际应用中需要替换为真正的按键检测代码 return 0; // 无按键 } void key_handle(void) { char key = get_key(); switch(key) { case 'A': // 切换温度单位 is_fahrenheit = !is_fahrenheit; printf("\n温度单位已切换为 %c\n", is_fahrenheit ? 'F' : 'C'); break; case 'B': // 进入温度设置 set_alarm_range(); break; case 'C': // 进入时间设置 set_time(); break; case '#': // 确认设置 save_settings(); break; } } // ====================== // 延时函数 // ====================== void delay_ms(unsigned int ms) { clock_t start_time = clock(); while (clock() < start_time + ms * CLOCKS_PER_SEC / 1000); } // ====================== // 设置函数 // ====================== void set_alarm_range(void) { printf("\n进入温度阈值设置模式\n"); printf("当前阈值: %.1f-%.1f°C\n", alarm_low, alarm_high); printf("在实际应用中,您可以通过按键调整这些值\n"); // 实际应用中需要通过按键调整 } void set_time(void) { printf("\n进入时间设置模式\n"); printf("在实际应用中,您可以通过按键调整时间\n"); // 实际应用中需要通过按键调整 } void save_settings(void) { printf("\n设置已保存\n"); // 实际应用中需要实现保存功能 }
最新发布
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值