1290 Counting Diff Pairs

本文提供了一种解决长度为N的正整数数组A中,求从A[i]到A[j]中,有多少对数满足abs(A[i]-A[j]) <= K的算法题解,通过莫队算法和树状数组实现。
题目来源: Spoj
基准时间限制: 4 秒 空间限制: 131072 KB 分值: 320 难度:7级算法题
收藏
关注
取消关注
一个长度为N的正整数数组A,给出一个数K以及Q个查询,每个查询包含2个数l和r,对于每个查询输出从A[i]到A[j]中,有多少对数,abs(A[i] - A[j]) <= K(abs表示绝对值)。

Input

第1行:3个数N,K,Q,中间用空格分隔,N为数组A的长度,K为差距,Q为查询的数量。(2 <= N <= 50000, 0 <= K <= 10^9, 1 <= Q <= 50000)第2至N + 1行:每行1个数,对应数组中的数(1 <= A[i] <= 10^9)第N + 2至N + M + 1行:每行2个数l, r中间用空格分隔(0 <= l <= r < N)

Output

输出共Q行,对于Q条查询的结果。

Input示例

5 2 3134300 11 30 4

Output示例

136


题解: 莫队加树状数组乱搞

AC代码:

#include <bits/stdc++.h>
#include <stdio.h>
#include <algorithm>

using namespace std;
typedef long long ll;
const int N = 5e5 + 5;

typedef pair<int,int> P;
P tmp[N];
int tid[N];

template<class T>
void read(T & x) {
    char ch = getchar();
    bool sign = false;
    x = 0;
    while (ch < '0' || ch > '9') {
        if (ch == '-') sign = true;
        ch = getchar();
    }
    while ('0' <= ch && ch <= '9') {
        x = 10 * x + ch - '0';
        ch = getchar();
    }
    if (sign) x = -x;
}

template<class T>
void print(T x) {
    if (x > 9) print(x / 10);
    putchar('0' + (x % 10));
}

template<class T>
void println(T x) {
    print(x);
    puts("");
}

template<class T>
inline T sqr(T a) {
    return a * a;
}
int c[N],a[N],b[N],n,unit,k,q;
ll ans[N];

int find(int x) {
    int l = 0,r = n - 1;
    int ans = 0;
    while(l <= r) {
        int mid = l + r >> 1;
        if(a[mid] < x) l = mid + 1;
        else if(a[mid] == x) {
            return mid;
        } else r = mid - 1;
    }
    return l;
}

inline int ID(int x,int v) {
    int id = find(x);
    if(v) id++;
    else if(id < n && a[id] == x) id++;
    return id;
}

void add(int x,int d) {
    while(x <= n) {
        c[x] += d;
        x += x & -x;
    }
}

int que(int l,int r) {
    int s = 0;
    while(r > 0) {
        s += c[r];
        r -= r & -r;
    }
    l--;
    while(l > 0) {
        s -= c[l];
        l -= l & -l;
    }
    return s;
}

struct node {
    int l,r,id;
    void read(int i) {
        id = i;
        scanf("%d %d",&l,&r);
    }
    bool operator < (const node &a) const {
        if((l + 1) / unit != (a.l + 1) / unit) return (l + 1) / unit < (a.l + 1) / unit;
        return (r + 1) < a.r + 1;
    }
}p[N];

void work() {
    ll temp = 0;
    int L = 1,R = 0;
    for(int i = 0; i < q; i++) {
        int l = p[i].l,r = p[i].r;
        while(R < r) {
            R++;
            temp += que(tmp[R].first,tmp[R].second);
            add(tid[R],1);
        }
        while(R > r) {
            add(tid[R],-1);
            temp -= que(tmp[R].first,tmp[R].second);
            R--;
        }
        while(L > l) {
            L--;
            temp += que(tmp[L].first,tmp[L].second);
            add(tid[L],1);
        }
        while(L < l) {
            add(tid[L],-1);
            temp -= que(tmp[L].first,tmp[L].second);
            L++;
        }
        ans[p[i].id] = temp;
    }
}

int main() {
    int NB;
    //freopen("in.txt","r",stdin);
    read(n),read(k),read(q);
    NB = n;
    for(int i = 0; i < n; i++) {
        read(a[i]);
        b[i] = a[i];
    }
    sort(a,a + n);
    unit = (int) sqrt(n + 0.5);
    n = unique(a,a + n) - a;
    for(int i = 0; i < NB; i++) {
        tmp[i].first = ID(b[i] - k,1);
        tmp[i].second = ID(b[i] + k,0);
        tid[i] = ID(b[i],1);

    }
    for(int i = 0; i < q; i++) p[i].read(i);
    sort(p,p + q);
    work();
    for(int i = 0; i < q; i++) {
        println(ans[i]);
    }
    return 0;
}


import cv2 import numpy as np from ultralytics import YOLO from filterpy.kalman import KalmanFilter import time from collections import deque import pyttsx3 import threading from PIL import Image, ImageDraw, ImageFont # --- 更新后的配置参数 --- CONFIG = { 'CLASS_NAMES': {2: "轿车", 5: "公交车", 7: "卡车"}, 'MOVING_COLOR': (0, 255, 0), # 正常行驶车辆颜色 (绿色) 'ABNORMAL_COLOR': (0, 0, 255), # 异常状态车辆颜色 (红色) 'CONFIDENCE_THRESHOLD': 0.3, # YOLO检测置信度阈值 'COUNT_LINE_POSITION': 0.6, # 计数线位置(屏幕高度的比例) 'SPEED_CALCULATION_WINDOW_SECONDS': 1.0, # 速度计算时间窗口 'ABNORMAL_SPEED_THRESHOLD_KMH': 20.0, # 异常状态速度阈值 (20 km/h) 'ABNORMAL_DURATION_THRESHOLD': 3.0, # 异常状态持续时间阈值 (3秒) 'FOCAL_LENGTH_PX': 1200, # 焦距(像素) 'REFERENCE_HEIGHTS': { # 各类车辆的实际参考高度(单位:米) 2: 1.5, # 轿车 5: 3.0, # 公交车 7: 3.5 # 卡车 }, 'FONT_PATH': 'simhei.ttf', # 中文字体文件路径 # 移除了COUNTING_DIRECTION配置项 } # 中文显示工具类(保持不变) class ChineseDisplay: def __init__(self, font_path='simhei.ttf', font_size=20): try: self.font = ImageFont.truetype(font_path, font_size) self.large_font = ImageFont.truetype(font_path, 24) self.small_font = ImageFont.truetype(font_path, 18) print(f"成功加载字体: {font_path}") except IOError: print(f"警告: 无法加载字体 {font_path}, 将使用默认字体") self.font = ImageFont.load_default() self.large_font = ImageFont.load_default() self.small_font = ImageFont.load_default() def draw_chinese_text(self, frame, text, position, color=(255, 255, 255), font_size='normal'): img_pil = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(img_pil) if font_size == 'large': font = self.large_font elif font_size == 'small': font = self.small_font else: font = self.font draw.text(position, text, font=font, fill=color) return cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR) # 语音播报管理器(保持不变) class VoiceAnnouncer: def __init__(self): self.engine = pyttsx3.init() self.engine.setProperty('rate', 150) self.engine.setProperty('volume', 0.8) self.announced_abnormal = set() self.lock = threading.Lock() def announce_abnormal(self, track_id, vehicle_type, duration): with self.lock: if track_id not in self.announced_abnormal: message = f"检测到车辆 {track_id} 号,{vehicle_type},状态异常" print(f"【语音播报】: {message}") def speak(): try: self.engine.say(message) self.engine.runAndWait() except Exception as e: print(f"语音播报错误: {e}") thread = threading.Thread(target=speak) thread.daemon = True thread.start() self.announced_abnormal.add(track_id) def reset_announcements(self): with self.lock: self.announced_abnormal.clear() # 卡尔曼滤波器初始化(保持不变) def init_kalman(x, y, fps): kf = KalmanFilter(dim_x=4, dim_z=2) dt = 1.0 / fps kf.F = np.array([[1, 0, dt, 0], [0, 1, 0, dt], [0, 0, 1, 0], [0, 0, 0, 1]]) kf.H = np.array([[1, 0, 0, 0], [0, 1, 0, 0]]) kf.P *= 10.0 kf.R = np.array([[1, 0], [0, 1]]) * 5 kf.Q = np.eye(4) * 0.1 kf.x = np.array([x, y, 0, 0]) return kf # 获取跟踪结果(保持不变) def get_tracks(image, model): boxes = [] results = model.track(image, persist=True, tracker="./bytetrack.yaml", verbose=False, conf=CONFIG['CONFIDENCE_THRESHOLD'], iou=0.5, classes=[2, 5, 7]) if results[0].boxes.id is None: return boxes result_boxes = results[0].boxes for box in result_boxes: if box.is_track: bbox = box.xyxy.cpu().numpy()[0] cls_id = int(box.cls.cpu().numpy()[0]) track_id = int(box.id.cpu().numpy()[0]) center_x = (bbox[0] + bbox[2]) / 2 center_y = (bbox[1] + bbox[3]) / 2 boxes.append({ 'track_id': track_id, 'cls_id': cls_id, 'bbox': bbox, 'center': (center_x, center_y), 'bottom_center': (center_x, bbox[3]), 'height': bbox[3] - bbox[1] }) return boxes # 绘制速度和状态信息(保持不变) def draw_vehicle_info(frame, chinese_display, bbox, speed_kmh, is_abnormal, abnormal_duration, cls_id, track_id): x1, y1, x2, y2 = bbox.astype(int) class_name = CONFIG['CLASS_NAMES'].get(cls_id, "车辆") speed_text = f"{speed_kmh:.1f} km/h" if is_abnormal: info_text = f"ID:{track_id} {class_name} {speed_text}" status_text = f"异常状态: {abnormal_duration:.1f}秒" frame = chinese_display.draw_chinese_text( frame, status_text, (x1, y1 - 40), color=CONFIG['ABNORMAL_COLOR'], font_size='small' ) else: info_text = f"ID:{track_id} {class_name} {speed_text}" frame = chinese_display.draw_chinese_text( frame, info_text, (x1, y1 - 15), color=(255, 255, 255), font_size='small' ) return frame # 计算实际距离(保持不变) def calculate_distance(pixel_height, cls_id): if cls_id not in CONFIG['REFERENCE_HEIGHTS']: return None reference_height = CONFIG['REFERENCE_HEIGHTS'][cls_id] focal_length = CONFIG['FOCAL_LENGTH_PX'] distance = (reference_height * focal_length) / pixel_height return distance # 主函数 def main(source): yolo = YOLO("yolo11n.pt") cap = cv2.VideoCapture(source) if not cap.isOpened(): print("无法打开视频源,请检查路径是否正确") return chinese_display = ChineseDisplay(CONFIG['FONT_PATH']) announcer = VoiceAnnouncer() fps = cap.get(cv2.CAP_PROP_FPS) or 30.0 frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) print(f"视频信息: {frame_width}x{frame_height}, {fps:.1f} FPS") count_line_y = int(frame_height * CONFIG['COUNT_LINE_POSITION']) track_states = {} traffic_stats = { 'total_count': 0, 'car_count': 0, 'bus_count': 0, 'truck_count': 0, 'current_normal': 0, 'current_abnormal': 0 } counted_vehicles = set() speed_window_size = int(CONFIG['SPEED_CALCULATION_WINDOW_SECONDS'] * fps) # 记录未计数的车辆(用于调试) uncounted_vehicles = set() while True: ret, frame = cap.read() if not ret: break current_time = time.time() tracks = get_tracks(frame, yolo) traffic_stats['current_normal'] = 0 traffic_stats['current_abnormal'] = 0 # 绘制计数线 cv2.line(frame, (0, count_line_y), (frame_width, count_line_y), (255, 255, 0), 2) frame = chinese_display.draw_chinese_text( frame, f"计数线 ({count_line_y}px)", (10, count_line_y - 15), color=(255, 255, 0), font_size='small' ) for track in tracks: track_id = track['track_id'] cls_id = track['cls_id'] bbox = track['bbox'] center = track['center'] bottom_center = track['bottom_center'] pixel_height = track['height'] x1, y1, x2, y2 = bbox.astype(int) cx, cy = center bx, by = bottom_center # 初始化车辆状态跟踪 if track_id not in track_states: track_states[track_id] = { "kf": init_kalman(cx, cy, fps), "position_history": deque(maxlen=speed_window_size), "height_history": deque(maxlen=speed_window_size), "abnormal_start_time": None, "is_abnormal": False, "counted": False, "last_by": by, # 记录上一帧的底部y坐标 "crossed_line": False # 标记是否已经过线 } # 显示新车辆ID frame = chinese_display.draw_chinese_text( frame, f"新车辆: ID{track_id}", (x1, y1 - 70), color=(0, 255, 255), font_size='small' ) # 卡尔曼滤波更新 kf = track_states[track_id]["kf"] kf.predict() kf.update(np.array([cx, cy])) filtered_center = (kf.x[0], kf.x[1]) # 记录位置和高度历史 pos_history = track_states[track_id]["position_history"] height_history = track_states[track_id]["height_history"] pos_history.append((current_time, filtered_center[0], filtered_center[1], by)) height_history.append((current_time, pixel_height)) # 计算速度 speed_kmh = 0.0 if len(pos_history) >= 2 and len(height_history) >= 2: last_time, last_x, last_y, last_by = pos_history[-1] prev_time, prev_x, prev_y, prev_by = pos_history[0] time_diff = last_time - prev_time if time_diff > 0.1: pixel_dist = np.sqrt((last_x - prev_x) ** 2 + (last_y - prev_y) ** 2) if cls_id in CONFIG['REFERENCE_HEIGHTS'] and pixel_height > 0: last_distance = calculate_distance(height_history[-1][1], cls_id) prev_distance = calculate_distance(height_history[0][1], cls_id) if last_distance is not None and prev_distance is not None: distance_diff = abs(last_distance - prev_distance) speed_mps = distance_diff / time_diff speed_kmh = speed_mps * 3.6 # 检测异常状态 is_abnormal = speed_kmh < CONFIG['ABNORMAL_SPEED_THRESHOLD_KMH'] abnormal_duration = 0.0 abnormal_start_time = track_states[track_id]["abnormal_start_time"] color = (255, 255, 255) if is_abnormal: if abnormal_start_time is None: abnormal_start_time = current_time else: abnormal_duration = current_time - abnormal_start_time if abnormal_duration > CONFIG['ABNORMAL_DURATION_THRESHOLD']: track_states[track_id]["is_abnormal"] = True traffic_stats['current_abnormal'] += 1 color = CONFIG['ABNORMAL_COLOR'] class_name = CONFIG['CLASS_NAMES'].get(cls_id, "车辆") announcer.announce_abnormal(track_id, class_name, abnormal_duration) else: track_states[track_id]["is_abnormal"] = False traffic_stats['current_normal'] += 1 color = (0, 255, 255) else: abnormal_start_time = None track_states[track_id]["is_abnormal"] = False traffic_stats['current_normal'] += 1 color = CONFIG['MOVING_COLOR'] track_states[track_id]["abnormal_start_time"] = abnormal_start_time # === 修改后的计数线逻辑:不再区分方向 === current_by = by last_by = track_states[track_id]["last_by"] # 判断车辆是否通过计数线(无论方向) crossed = False # 检测从上方穿过计数线(向下移动) if last_by <= count_line_y and current_by > count_line_y: crossed = True # 检测从下方穿过计数线(向上移动) if last_by >= count_line_y and current_by < count_line_y: crossed = True # 更新上一帧的底部y坐标 track_states[track_id]["last_by"] = current_by # 如果检测到穿过计数线且未计数 if crossed and not track_states[track_id]["counted"]: track_states[track_id]["counted"] = True track_states[track_id]["crossed_line"] = True counted_vehicles.add(track_id) traffic_stats['total_count'] += 1 if cls_id == 2: traffic_stats['car_count'] += 1 elif cls_id == 5: traffic_stats['bus_count'] += 1 elif cls_id == 7: traffic_stats['truck_count'] += 1 # 显示计数信息 frame = chinese_display.draw_chinese_text( frame, f"计数: ID{track_id}", (x1, y1 - 85), color=(0, 255, 0), font_size='small' ) # 显示计数线判断信息(用于调试) count_status = "已计数" if track_states[track_id]["counted"] else "未计数" frame = chinese_display.draw_chinese_text( frame, f"计数状态: {count_status}", (x1, y1 - 100), color=(200, 200, 255) if not track_states[track_id]["counted"] else (0, 255, 0), font_size='small' ) # 绘制车辆边界框和信息 cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2) frame = draw_vehicle_info( frame, chinese_display, bbox, speed_kmh, track_states[track_id]["is_abnormal"], abnormal_duration, cls_id, track_id ) # 显示距离信息 if cls_id in CONFIG['REFERENCE_HEIGHTS']: distance = calculate_distance(pixel_height, cls_id) if distance is not None: frame = chinese_display.draw_chinese_text( frame, f"距离: {distance:.1f}米", (x1, y1 - 55), color=(200, 200, 255), font_size='small' ) # 显示统计信息 stats_texts = [ f"总车辆: {traffic_stats['total_count']} (轿车: {traffic_stats['car_count']}, 公交: {traffic_stats['bus_count']}, 卡车: {traffic_stats['truck_count']})", f"正常: {traffic_stats['current_normal']} | 异常: {traffic_stats['current_abnormal']}", f"帧率: {fps:.1f} FPS" ] for i, text in enumerate(stats_texts): frame = chinese_display.draw_chinese_text( frame, text, (10, 30 + i * 25), color=(255, 255, 255), font_size='small' ) # 显示状态说明 frame = chinese_display.draw_chinese_text( frame, "绿色: 正常行驶 | 黄色: 低速警告 | 红色: 异常状态", (10, frame_height - 20), color=(255, 255, 255), font_size='small' ) # 显示计数线位置(不再显示方向) count_line_text = f"计数线位置: y={count_line_y}px" frame = chinese_display.draw_chinese_text( frame, count_line_text, (frame_width - 200, frame_height - 20), color=(255, 255, 0), font_size='small' ) cv2.imshow("高速公路车辆状态监测", frame) # 键盘控制 key = cv2.waitKey(1) & 0xFF if key == ord("q"): break elif key == ord(" "): cv2.waitKey(0) elif key == ord("r"): traffic_stats = {k: 0 for k in traffic_stats} counted_vehicles.clear() track_states.clear() announcer.reset_announcements() print("所有计数器和状态已重置") elif key == ord("c"): # 调整计数线位置 CONFIG['COUNT_LINE_POSITION'] += 0.05 if CONFIG['COUNT_LINE_POSITION'] > 0.95: CONFIG['COUNT_LINE_POSITION'] = 0.1 count_line_y = int(frame_height * CONFIG['COUNT_LINE_POSITION']) print(f"计数线位置调整为: {CONFIG['COUNT_LINE_POSITION']} (y={count_line_y}px)") # 更新实时帧率 fps = cap.get(cv2.CAP_PROP_FPS) # 释放资源 cap.release() cv2.destroyAllWindows() print("\n=== 最终交通统计 ===") print(f"总车辆数: {traffic_stats['total_count']}") print(f"轿车: {traffic_stats['car_count']}") print(f"公交车: {traffic_stats['bus_count']}") print(f"卡车: {traffic_stats['truck_count']}") print(f"检测到异常状态车辆: {traffic_stats['current_abnormal']}") if __name__ == "__main__": main("video/04-12_09_K221_1953.mp4")代码运行结果显示视频中车辆速度瞬时变化非常大,检测的车速不稳定,修改
最新发布
11-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值