当前位置: 首页 > news >正文

洛谷P4479第K大斜率

P4479第K大斜率
我采用了二分答案和树状数组统计顺序对的方法解决第k大斜率问题。以下是对代码思路的总结和关键点分析:

代码思路总结:

  1. 输入与预处理

    • 读入 n 个点的坐标,存储到数组 arr 中。
    • 对点按 x 坐标升序排序,若 x 相同则按 y 降序排序(避免斜率不存在的点对影响统计)。
  2. 二分答案框架

    • 二分斜率 mid,初始范围 [-1e9, 1e9]
    • 对于每个 mid,通过 check(mid) 函数判断是否存在至少 k 条直线的斜率 ≥ mid
  3. check(mid) 函数

    • 计算转换值:对每个点计算转换值 z_i = y_i - mid * x_i
    • 离散化:将 z_i 排序并离散化为排名(相同值赋予相同排名)。
    • 树状数组统计顺序对
      • 按原顺序(排序后的点顺序)遍历每个点。
      • 查询树状数组中排名 ≤ 当前点排名的点的个数(即满足 z_j ≥ z_ij < i 的点对数)。
      • 累加顺序对数量,若累计值 ≥ k 则返回 true
      • 更新树状数组(当前点排名位置 +1)。
    • 若遍历结束累计值 < k,返回 false
  4. 二分调整

    • check(mid)true,说明 mid 偏小(有足够多斜率 ≥ mid 的直线),调整左边界 l = mid
    • 若为 false,说明 mid 偏大,调整右边界 r = mid
    • 最终 l 即为第 k 大斜率的向下取整结果。
  5. 输出:二分结束后输出 l

关键点分析:

  • 避免斜率不存在:通过排序策略(x 相同时 y 降序)确保 x 相同的点不会产生有效顺序对(因 z_i 严格递减),从而排除斜率不存在的点对。
  • 离散化优化:将 z_i 离散化为排名,将值域压缩到 [1, n],适合树状数组处理。
  • 顺序对统计:树状数组动态维护已遍历点的排名分布,高效查询当前点的顺序对数量。
  • 二分正确性:二分目标为最大的 mid 满足至少 k 条直线斜率 ≥ mid,该 mid 即第 k 大斜率的向下取整值。
  • 复杂度:二分过程 O(log(2e9)),每次 check 离散化 O(n log n),树状数组操作 O(n log n),总复杂度 O(n log n log(2e9)),可接受。

代码优化建议:

  1. 提前退出优化:在 check 函数中,一旦累计顺序对数量 ≥ k 即可提前返回 true,减少无效计算。
  2. 树状数组清零:每次 check 前通过初始化保证树状数组归零,避免脏数据。
  3. 离散化处理:对相同 z_i 赋予相同排名,确保顺序对统计正确性。

代码处理了边界情况(如大值域、斜率不存在、重复 z_i 等),能高效解决大规模数据问题。最终输出向下取整结果符合题目要求。

AC代码

#include<bits/stdc++.h>
#define ll long long
#define samplepassediscorrect for(;;)
#define ull unsigned long long
#define jiasu ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define lowbit(x) (x&(-x))
#define N 100050
using namespace std;
struct point{ll x,y;
}arr[N]; 
bool cmp(point &s1,point &s2){if(s1.x==s2.x) return s1.y>s2.y;return s1.x<s2.x;
}
ll n,b[N],k;
struct Fenwick_Tree{ll tree[N]={0};void update(ll x,ll d){while(x<=n){tree[x]+=d;x+=lowbit(x);}}ll sum(ll x){ll ans=0;while(x>0){ans+=tree[x];x-=lowbit(x);}return ans;}
}; 
struct temp{ll x,num;
}a[N];
bool cmp2(temp &s1,temp &s2){return s1.x<s2.x;}
bool check(ll mid){for(int i=1;i<=n;i++){a[i].num=i;a[i].x=arr[i].y-mid*arr[i].x;}sort(a+1,a+1+n,cmp2);b[a[1].num]=1;ll now=a[1].x,cnt=1;for(int i=2;i<=n;i++){if(a[i].x!=now){b[a[i].num]=++cnt;now=a[i].x;}else b[a[i].num]=cnt;}Fenwick_Tree r;ll sum=0;for(int i=1;i<=n;i++){		sum+=r.sum(b[i]);r.update(b[i],1);if(sum>=k) return true;}	return false;
}
int main(){
jiasu;
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>arr[i].x>>arr[i].y;
sort(arr+1,arr+1+n,cmp);
ll l=-1e9,r=1e9;
while(l+1<r){ll mid=(l+r)/2;if(check(mid)) l=mid;else r=mid;
}
cout<<l;return 0;
} 
http://www.dtcms.com/a/309616.html

相关文章:

  • OSPF笔记整理
  • Transformer架构全解析:搭建AI的“神经网络大厦“
  • 开箱即用的Next.js SSR企业级开发模板
  • 【性能测试】混合业务场景TPS+内存溢出定位分析+调优和分析(详情)
  • 猫眼浏览器:简约安全的 Chrome 内核增强版浏览器
  • 【JVM篇13】:兼顾吞吐量和低停顿的G1垃圾回收器
  • UniappDay06
  • wsl /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.28‘ not found
  • 【Spring 】Spring Cloud Gateway 直连 Istio 服务网格深度集成方案
  • 使用uniapp开发小程序-【引入字体并全局使用】
  • 软件测试测评公司关于HTTP安全头配置与测试?
  • 07 连锁不平衡和群体结构分析原理
  • 理想I8对撞乘龙卡车,AI基于数学和物理的角度如何看?
  • 应急响应(windows工具版)
  • echarts一个图例控制多个图表
  • Git 进阶使用
  • ansible 在EE 容器镜像中运行
  • C primer plus (第六版)第十章 编程练习第7,8,9,10,11题
  • Linux基本服务——web服务解析
  • 如何管理数据足迹,实现SAP S/4HANA的无缝迁移
  • Solana: 逐行解读 solana-test-validator 输出, 本地节点日志完全指南
  • oracle备库主机断电重启后IO异常报错
  • 【C#学习Day16笔记】XML文件、 事件Event 、Json数据
  • Sqlserver备份恢复指南-完整备份恢复
  • 从零到英雄:掌握神经网络的完整指南
  • Qt Quick 自定义组件开发
  • 江协科技STM32 11-4 SPI通信外设
  • Android SDK 版本差异与兼容方案:从适配到实践
  • gitlab 开发人员无法创建分支,管理员配置分支权限
  • flutter-boilerplate-project 学习笔记