CF1527C Sequence Pair Weight

博客介绍了CF1527C问题的解决方案,主要内容涉及如何计算序列中相等元素形成的连续区间的数对之和。通过分析相等数对对总和的贡献,并利用离散化技术简化处理大规模值域的问题。

传送门

题目大意

给定一个长度为 n n n 的序列 a a a,求:
∑ 1 ≤ l < r ≤ n ∑ l ≤ x < y ≤ r [ a x = a y ] \sum_{1\le l<r\le n}\sum_{l\le x<y\le r}[a_x=a_y] 1l<rnlx<yr[ax=ay]
即:求每一个连续区间内的相等数对之和。

Solution

套路题,如果直接求不好求,那么算每一部分的贡献。

首先考虑如果两个数 a i = a j a_i=a_j ai=aj i < j i<j i<j),那么其产生的贡献是 i × ( n − j + 1 ) i\times (n-j+1) i×(nj+1),也就是有 i × ( n − j + 1 ) i\times (n-j+1) i×(nj+1) 个区间包含它。

此时考虑如果有第三个 a k = a i = a j a_k=a_i=a_j ak=ai=aj k > j k>j k>j),这个时候贡献会加上:
i × ( n − k + 1 ) + j × ( n − k + 1 ) i\times (n-k+1)+j\times (n-k+1) i×(nk+1)+j×(nk+1)
= ( i + j ) × ( n − k + 1 ) =(i+j)\times (n-k+1) =(i+j)×(nk+1)

于是我们想到,对于每一个值,我们记录这个值的下标的和为 s u m sum sum,当这个值新加入了一个下标时,我用这个和来更新答案:
a n s = a n s + s u m × ( n − i + 1 ) ans=ans+sum\times (n-i+1) ans=ans+sum×(ni+1)
其中 i i i 为新加入的下标。

那么问题是值域比较大,所以用到离散化即可。

Code

#include<bits/stdc++.h>
#define inf 1<<30
#define INF 1ll<<60
#define ll long long
using namespace std;
const int MAXN=1e5+10;
int a[MAXN],b[MAXN];
ll sum[MAXN];
void solve(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+1+n);
	int cnt=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+cnt,a[i])-b;
	//离散化
	ll ans=0;
	for(int i=1;i<=n;i++){
		if(!sum[a[i]]) sum[a[i]]+=i;
		else{
			ans+=sum[a[i]]*(n-i+1);
			sum[a[i]]+=i;
		}
	}printf("%lld\n",ans);
	for(int i=1;i<=cnt;i++) sum[i]=0;//注意不要用 memset 全部更新,这题能卡掉(亲测)
}
int main()
{
	int T;
	for(scanf("%d",&T);T--;)
		solve();
}
上面代码运行后提示python里面不包含openrouteservice 的模块,需要按照以下代码的调用格式进行改进: import requests import json import folium import pandas as pd import numpy as np from datetime import datetime import webbrowser import os import math class OpenRouteService: def __init__(self, api_key): self.api_key = api_key self.base_url = "https://api.openrouteservice.org" def get_directions(self, coordinates, profile='driving-car'): """获取路径规划""" headers = { 'Authorization': self.api_key, 'Content-Type': 'application/json' } body = { "coordinates": coordinates, "instructions": "false", "geometry": "true" } print("正在调用OpenRouteService API...") try: response = requests.post( f"{self.base_url}/v2/directions/{profile}/geojson", json=body, headers=headers, timeout=30 ) if response.status_code == 200: print("API调用成功!") return response.json() else: print(f"API调用失败: {response.status_code}") print(f"错误信息: {response.text}") return None except Exception as e: print(f"API请求异常: {e}") return None def parse_route_data(ors_result, timestamps): """解析路由据并计算速度""" if not ors_result or 'features' not in ors_result or not ors_result['features']: print("未找到有效的路径据") return None, None, None, None feature = ors_result['features'][0] geometry = feature['geometry'] properties = feature.get('properties', {}) # 提取路径坐标 route_coords = [] if geometry['type'] == 'LineString': # 转换坐标顺序: [经度, 纬度] -> (纬度, 经度) route_coords = [(coord[1], coord[0]) for coord in geometry['coordinates']] # 检查是否有segments据 if 'segments' not in properties or not properties['segments']: print("警告: 返回的据中没有segments信息,使用简化计算") # 使用简化方法计算距离和速度 return calculate_simple_speed(route_coords, timestamps) # 提取分段信息 segments = properties['segments'][0] total_distance = segments.get('distance', 0) # 米 total_duration = segments.get('duration', 0) # 秒 # 计算平均速度 if total_duration > 0: avg_speed = (total_distance / total_duration) * 3.6 # km/h else: avg_speed = 0 print(f"路径总距离: {total_distance:.2f} 米") print(f"路径总时间: {total_duration:.2f} 秒") print(f"平均速度: {avg_speed:.2f} km/h") # 计算分段速度(如果有多个分段) step_speeds = [] step_distances = [] if 'steps' in segments: for step in segments['steps']: distance = step.get('distance', 0) duration = step.get('duration', 0) if duration > 0: speed = (distance / duration) * 3.6 else: speed = 0 step_speeds.append(speed) step_distances.append(distance) else: # 如果没有steps,使用总距离和总时间 if total_duration > 0: step_speeds.append(avg_speed) step_distances.append(total_distance) return route_coords, step_speeds, step_distances, avg_speed def calculate_simple_speed(route_coords, timestamps): """简化计算速度(当API返回据不完整时使用)""" if not route_coords or len(route_coords) < 2: return None, None, None, 0 # 计算总距离(使用Haversine公式计算实际地理距离) total_distance = 0 for i in range(len(route_coords) - 1): # 使用Haversine公式计算两点间距离 lat1, lon1 = route_coords[i] lat2, lon2 = route_coords[i + 1] distance = haversine_distance(lon1, lat1, lon2, lat2) total_distance += distance # 计算总时间 total_duration = (timestamps[-1] - timestamps[0]).total_seconds() # 计算平均速度 if total_duration > 0: avg_speed = (total_distance / total_duration) * 3.6 # km/h else: avg_speed = 0 print(f"简化计算 - 路径总距离: {total_distance:.2f} 米") print(f"简化计算 - 路径总时间: {total_duration:.2f} 秒") print(f"简化计算 - 平均速度: {avg_speed:.2f} km/h") # 创建简化的分段据 step_speeds = [avg_speed] # 使用平均速度作为分段速度 step_distances = [total_distance] # 使用总距离作为分段距离 return route_coords, step_speeds, step_distances, avg_speed def haversine_distance(lon1, lat1, lon2, lat2): """使用Haversine公式计算两点间距离(米)""" R = 6371000 # 地球半径(米) dlat = math.radians(lat2 - lat1) dlon = math.radians(lon2 - lon1) a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) * math.sin(dlon / 2)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) return R * c def create_visualization(original_points, route_coords, step_speeds, person_id, output_dir="./output"): """创建可视化地图并保存结果""" if not os.path.exists(output_dir): os.makedirs(output_dir) # 创建地图 - 郑州大学为中心 center_lat = 34.817 # 郑州大学大致纬度 center_lon = 113.536 # 郑州大学大致经度 m = folium.Map(location=[center_lat, center_lon], zoom_start=15) # 添加原始点标记 for i, point in enumerate(original_points): folium.Marker( location=[point[1], point[0]], # (纬度, 经度) popup=f"人员 {person_id}<br>点 {i + 1}<br>经度: {point[0]:.6f}<br>纬度: {point[1]:.6f}", icon=folium.Icon(color='red', icon='user') ).add_to(m) # 添加路径 if route_coords: # 根据速度给路径着色 avg_speed = np.mean(step_speeds) if step_speeds else 0 if avg_speed < 1: color = 'gray' elif avg_speed < 3: color = 'blue' elif avg_speed < 5: color = 'green' elif avg_speed < 10: color = 'orange' else: color = 'red' folium.PolyLine( route_coords, color=color, weight=6, opacity=0.7, popup=f"人员 {person_id} 轨迹<br>平均速度: {avg_speed:.1f} km/h" ).add_to(m) # 添加起点终点标记 folium.Marker( location=route_coords[0], popup="起点", icon=folium.Icon(color='green', icon='play') ).add_to(m) folium.Marker( location=route_coords[-1], popup="终点", icon=folium.Icon(color='red', icon='stop') ).add_to(m) # 添加郑州大学标记 folium.Marker( location=[34.817, 113.536], popup="郑州大学", icon=folium.Icon(color='purple', icon='education') ).add_to(m) # 保存地图 map_file = os.path.join(output_dir, f"route_visualization_{person_id}.html") m.save(map_file) print(f"地图已保存至: {map_file}") return map_file def save_results_to_csv(original_points, route_coords, step_speeds, step_distances, timestamps, person_id, output_dir="./output"): """保存结果到CSV文件""" if not os.path.exists(output_dir): os.makedirs(output_dir) # 保存原始点据 original_data = [] for i, point in enumerate(original_points): original_data.append({ 'person_id': person_id, 'point_id': i + 1, 'longitude': point[0], 'latitude': point[1], 'timestamp': timestamps[i] if i < len(timestamps) else None }) df_original = pd.DataFrame(original_data) original_csv = os.path.join(output_dir, f"original_points_{person_id}.csv") df_original.to_csv(original_csv, index=False, encoding='utf-8-sig') print(f"原始点据已保存至: {original_csv}") # 保存路径点据 if route_coords: route_data = [] for i, coord in enumerate(route_coords): route_data.append({ 'person_id': person_id, 'route_point_id': i + 1, 'latitude': coord[0], 'longitude': coord[1] }) df_route = pd.DataFrame(route_data) route_csv = os.path.join(output_dir, f"route_points_{person_id}.csv") df_route.to_csv(route_csv, index=False, encoding='utf-8-sig') print(f"路径点据已保存至: {route_csv}") # 保存分段速度据 if step_speeds and step_distances: speed_data = [] for i, (speed, distance) in enumerate(zip(step_speeds, step_distances)): speed_data.append({ 'person_id': person_id, 'segment_id': i + 1, 'distance_m': distance, 'speed_kmh': speed, 'start_time': timestamps[i] if i < len(timestamps) else None, 'end_time': timestamps[i + 1] if i + 1 < len(timestamps) else None }) df_speed = pd.DataFrame(speed_data) speed_csv = os.path.join(output_dir, f"segment_speeds_{person_id}.csv") df_speed.to_csv(speed_csv, index=False, encoding='utf-8-sig') print(f"分段速度据已保存至: {speed_csv}") def open_map_in_browser(map_file): """在浏览器中打开地图""" try: webbrowser.open('file://' + os.path.abspath(map_file)) print("正在浏览器中打开地图...") except Exception as e: print(f"无法在浏览器中打开地图: {e}") print(f"请手动打开文件: {os.path.abspath(map_file)}") def parse_timestamp(timestamp_str): """解析时间戳字符串""" try: # 处理毫秒时间戳 if '.' in timestamp_str: return datetime.strptime(timestamp_str, '%Y-%m-%dT%H:%M:%S.%f') else: return datetime.strptime(timestamp_str, '%Y-%m-%dT%H:%M:%S') except Exception as e: print(f"时间解析错误: {e}") return datetime.now() def process_person_trajectory(person_data, api_key): """处理单个人的轨迹据""" # 按时间排序 person_data.sort(key=lambda x: x['timestamp']) # 提取坐标和时间 coordinates = [[point['longitude'], point['latitude']] for point in person_data] timestamps = [point['timestamp'] for point in person_data] person_id = person_data[0]['person_id'] if person_data else "unknown" print(f"\n处理人员 {person_id} 的轨迹据...") print(f"据点: {len(coordinates)}") ors = OpenRouteService(api_key) # 获取路径规划 result = ors.get_directions(coordinates) if result: # 解析据 route_coords, step_speeds, step_distances, avg_speed = parse_route_data(result, timestamps) if route_coords: # 创建可视化 map_file = create_visualization(coordinates, route_coords, step_speeds, person_id) # 保存结果到CSV save_results_to_csv(coordinates, route_coords, step_speeds, step_distances, timestamps, person_id) # 在浏览器中打开地图 open_map_in_browser(map_file) print(f"\n=== 人员 {person_id} 处理完成 ===") print(f"• 可视化地图: {os.path.abspath(map_file)}") print(f"• 据文件保存在: {os.path.abspath('./output')} 目录") return True else: print(f"无法解析人员 {person_id} 的路径据") return False else: print(f"无法获取人员 {person_id} 的路径规划结果") return False # 使用示例 - 郑州大学轨迹分析 def zhengzhou_university_example(): # 替换为你的实际API密钥 api_key = "eyJvcmciOiI1YjNjZTM1OTc4NTExMTAwMDFjZjYyNDgiLCJpZCI6IjdjMjYxY2Q2NzgyNjRlYjViOWRiODBlOTIxZTE3NDA1IiwiaCI6Im11cm11cjY0In0=" if api_key == "YOUR_OPENROUTESERVICE_API_KEY": print("请先设置你的OpenRouteService API密钥!") return # 郑州大学实际点位据 raw_data = [ "郑州大学点,2024-7-13T11:55:10,0000897851,113.529859103333,34.81229556", "郑州大学点,2024-7-13T12:00:33,0000897851,113.5240264075,34.813994935" ] # 解析据 person_data = [] for line in raw_data: parts = line.split(',') if len(parts) >= 5: person_data.append({ 'location': parts[0], 'timestamp': parse_timestamp(parts[1]), 'person_id': parts[2], 'longitude': float(parts[3]), 'latitude': float(parts[4]) }) # 按人员ID分组处理(这里只有一个人员) persons = {} for data in person_data: person_id = data['person_id'] if person_id not in persons: persons[person_id] = [] persons[person_id].append(data) # 处理每个人的轨迹 success_count = 0 for person_id, data in persons.items(): if process_person_trajectory(data, api_key): success_count += 1 print(f"\n=== 总体处理完成 ===") print(f"成功处理 {success_count}/{len(persons)} 个人员的轨迹据") print(f"所有结果保存在: {os.path.abspath('./output')} 目录") if __name__ == "__main__": zhengzhou_university_example() # 添加暂停,确保能看到输出 input("按Enter键退出...")
11-21
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值