【学习笔记】CF607E Cross Sum

这篇具有很好参考价值的文章主要介绍了【学习笔记】CF607E Cross Sum。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

分为两个部分求解。

首先考虑找到距离 ≤ r \le r r的交点数量。发现这等价于圆上两段圆弧相交,因此将圆上的点离散化后排序,用一个主席树来求就做完了。

然后是距离求和。这看起来非常棘手。事实上,只要把所有交点都找出来就做完了。首先可以放心的将圆环从一个位置断开。其次,考虑以某种顺序将所有直线依次删掉。发现当按照长度从大到小删时,假设这条线段是 [ l i , r i ] [l_i,r_i] [li,ri],发现只要满足 l j ∈ [ l i , r i ] l_j\in [l_i,r_i] lj[li,ri]或者 r j ∈ [ l i , r i ] r_j\in [l_i,r_i] rj[li,ri],那么直线 i , j i,j i,j一定相交。那么前面一个问题也得到了解决,只需用树状树组维护就做完了。

当然,事实上我们可以 O ( 1 ) O(1) O(1)求出一个交点。考虑倒着做,每次删除一条线段,用链表维护就做完了。事实上交点在圆上的情况并不影响答案,所以可以少一些细节。文章来源地址https://www.toymoban.com/news/detail-430404.html

#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f
#define db double
#define cpx complex<db>
using namespace std;
const int N=1e5+5;
struct seg{
    db k,b;
}seg[N];
struct point{
    db x,y;
}p;
int n,m,cntseg,cnt;
int bit[N],sa[N],pos[N];
int le[N],ri[N],L[N],R[N];//链表
db res;
pair<db,int>A[N];
bool cmp(int x,int y){
    return R[x]-L[x]<R[y]-L[y];
}
ll ask(int x){
    ll tot=0;
    for(;x;x-=x&-x)tot+=bit[x];
    return tot;
}
void add(int x,int y){
    for(;x<=cnt;x+=x&-x)bit[x]+=y;
}
db getdist(point x,point y){
    return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}
point calc(int x,int y){
    x=pos[x],y=pos[y];
    db tx=(seg[y].b-seg[x].b)/(seg[x].k-seg[y].k),ty=seg[x].k*tx+seg[x].b;
    return {tx,ty};
}
void del(int x){
    if(le[x])ri[le[x]]=ri[x];
    if(ri[x])le[ri[x]]=le[x];
}
ll check(db mid){
    ll res=0;
    cntseg=cnt=0;
    for(int i=1;i<=n;i++){
        db dist=abs(seg[i].k*p.x-p.y+seg[i].b)/sqrt(seg[i].k*seg[i].k+1);
        if(dist<=mid){
            db a=seg[i].k*seg[i].k+1,b=2*seg[i].k*(seg[i].b-p.y)-2*p.x,c=p.x*p.x+(seg[i].b-p.y)*(seg[i].b-p.y)-mid*mid;
            db delta=b*b-4*a*c;
            db lx=(-b-sqrt(delta))/(2*a),ly=seg[i].k*lx+seg[i].b;
            db rx=(-b+sqrt(delta))/(2*a),ry=seg[i].k*rx+seg[i].b;
            cntseg++;
            L[cntseg]=R[cntseg]=0;
            //fixed
            pos[cntseg]=i;
            A[++cnt]={atan2(ry-p.y,rx-p.x),cntseg};
            A[++cnt]={atan2(ly-p.y,lx-p.x),cntseg};
        }
    }
    sort(A+1,A+1+cnt);
    for(int i=1;i<=cnt;i++){
        if(!L[A[i].se])L[A[i].se]=i;
        else R[A[i].se]=i;
    }
    for(int i=1;i<=cntseg;i++){
        sa[i]=i;
    }
    sort(sa+1,sa+1+cntseg,cmp);
    for(int i=1;i<=cnt;i++)le[i]=i-1,ri[i]=i+1;ri[cnt]=0;
    for(int i=1;i<=cnt;i++)add(i,1);
    for(int i=1;i<=cntseg;i++){
        int x=sa[i];
        res+=ask(R[x]-1)-ask(L[x]);
        add(L[x],-1),add(R[x],-1);
        del(L[x]),del(R[x]);
    }
    return res;
}
db getans(db mid){
    ll res=0;
    db tot=0;
    cntseg=cnt=0;
    for(int i=1;i<=n;i++){
        db dist=abs(seg[i].k*p.x-p.y+seg[i].b)/sqrt(seg[i].k*seg[i].k+1);
        if(dist<=mid){
            db a=seg[i].k*seg[i].k+1,b=2*seg[i].k*(seg[i].b-p.y)-2*p.x,c=p.x*p.x+(seg[i].b-p.y)*(seg[i].b-p.y)-mid*mid;
            db delta=b*b-4*a*c;
            db lx=(-b-sqrt(delta))/(2*a),ly=seg[i].k*lx+seg[i].b;
            db rx=(-b+sqrt(delta))/(2*a),ry=seg[i].k*rx+seg[i].b;
            cntseg++;
            L[cntseg]=R[cntseg]=0;
            //fixed
            pos[cntseg]=i;
            A[++cnt]={atan2(ry-p.y,rx-p.x),cntseg};
            A[++cnt]={atan2(ly-p.y,lx-p.x),cntseg};
        }
    }
    sort(A+1,A+1+cnt);
    for(int i=1;i<=cnt;i++){
        if(!L[A[i].se])L[A[i].se]=i;
        else R[A[i].se]=i;
    }
    for(int i=1;i<=cntseg;i++)sa[i]=i;
    sort(sa+1,sa+1+cntseg,cmp);
    for(int i=1;i<=cnt;i++)le[i]=i-1,ri[i]=i+1;ri[cnt]=0;
    for(int i=1;i<=cnt;i++)add(i,1);
    for(int i=1;i<=cntseg;i++){
        int x=sa[i];
        for(int j=ri[L[x]];j!=R[x];j=ri[j]){
            point tmp=calc(x,A[j].se);
            res++;
            tot+=getdist(p,tmp);
        }
        add(L[x],-1),add(R[x],-1);
        del(L[x]),del(R[x]);
    }
    return tot+(m-res)*mid;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>p.x>>p.y>>m;
    p.x/=1000,p.y/=1000;
    //fixed
    for(int i=1;i<=n;i++){
        cin>>seg[i].k>>seg[i].b;
        seg[i].k/=1000,seg[i].b/=1000;
    }
    db l=0,r=4e9;
    for(int i=1;i<=100;i++){
        db mid=(l+r)/2;
        if(check(mid)<=m)l=mid;
        else r=mid;
    }
    //fixed
    cout.precision(20);
    cout<<getans(l);
}

到了这里,关于【学习笔记】CF607E Cross Sum的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • web安全是什么?主要分为哪几部分?

    网络安全是一个非常庞大的体系,范围非常之大,被分为很多种类型,web安全就是其中之一,也是网络安全技术中非常重要的领域。那么web安全是什么?主要分为哪几部分?以下是详细的内容介绍。 什么是web安全? 随着web2.0、社交网络、微博等等一系列新型的互联网产品的诞生

    2024年02月09日
    浏览(46)
  • 【学习笔记】CF573E Bear and Bowling

    感觉贪心的做法比较自然🤔,推荐 这篇博客 非常经典 牛逼 的贪心思路: 考虑每次加入一个数,位置 i i i 的贡献为 V i = k i × a i + b i V_i=k_itimes a_i+b_i V i ​ = k i ​ × a i ​ + b i ​ ,其中 k i k_i k i ​ 表示 i i i 以前被选的位置的个数, b i b_i b i ​ 表示 i i i 以后被选的数的

    2024年02月07日
    浏览(34)
  • 【学习笔记】CF1783G Weighed Tree Radius

    如果 w v ( u ) w_v(u) w v ​ ( u ) 指代的就是直径,或者说我们再添一项 a v a_v a v ​ ,那么我们几乎就做完了。 于是自然而然想到换一个定义: d ( u , v ) = dist ( u , v ) + a u + a v d(u,v)=text{dist}(u,v)+a_u+a_v d ( u , v ) = dist ( u , v ) + a u ​ + a v ​ 。 发现这样转化过后,设直径的两个端点

    2024年02月16日
    浏览(36)
  • 【学习笔记】CF576D Flights for Regular Customers

    不同于传统的最短路,当我们走到一个节点的时候,还要记录此时经过的边数才能完成转移。但是第二维太大了,太抽象了! 看到 m m m 这么小,很难不想到离散化。那么设 f i , j f_{i,j} f i , j ​ 表示当第 i i i 条边出现时,在节点 j j j 是否可行,注意这是 01 01 01 状态。转移非

    2024年02月12日
    浏览(30)
  • 【学习笔记】CF582D Number of Binominal Coefficients

    注意 P P P 事实上不会影响复杂度,因为关于组合数,我们有一个非常经典的结论: ( n + m m ) binom{n+m}{m} ( m n + m ​ ) 包含的 P P P 的幂的次数等于 n n n 和 m m m 在 P P P 进制下做加法的进位次数。这样,我们只需要关心进位的次数,而不必知道每一位具体是多少。 这个结论的证

    2024年02月12日
    浏览(29)
  • 【学习笔记】CF1835D Doctor‘s Brown Hypothesis

    有点难😅 发现 x , y x,y x , y 在一个强连通块内,这样一定有环🤔 发现可以找到强连通块内所有环长度的 gcd ⁡ gcd g cd ,这样从 x x x 到 y y y 的所有路径的长度都模这个数同余,又因为 K K K 非常大,所以我们总可以遍历整个强连通块并走若干个环,因此只需要从 x x x 到 y y

    2024年02月09日
    浏览(32)
  • 今天吃什么小游戏(基于Flask框架搭建的简单应用程序,用于随机选择午餐选项。代码分为两部分:Python部分和HTML模板部分)

    今天吃什么 一个简单有趣的外卖点饭网站,不知道吃什么的时候,都可以用它自动决定你要吃的,包括各种烧烤、火锅、螺蛳粉、刀削面、小笼包、麦当劳等午餐全部都在内。点击开始它会随意调出不同的午餐,点击停止就会挑选一个你准备要吃的,如果没有想吃的,你还能

    2024年01月16日
    浏览(46)
  • 【算法】Maximum Sum of Two Non-Overlapping Subarrays 两个非重叠子数组的最大和

    问题 有一个整数数组nums,和2个整数firstlen,secondlen,要求找出2个非重叠子数组中的元素的最大和,长度分别是firstlen,secondlen。 不限制2个子数组的先后顺序。 firstlen,secondlen的范围 [ 1 , 1000 ] [1,1000] [ 1 , 1000 ] firstlen+secondlen的范围 [ 2 , 1000 ] [2,1000] [ 2 , 1000 ] f i r s t l e n ,

    2023年04月27日
    浏览(121)
  • redis学习笔记 - 进阶部分

    单线程:主要是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程。 多线程:主要

    2024年02月11日
    浏览(35)
  • SystemVerilog学习笔记(可综合的部分)(一)

             Verilog-1995有两种基本数据类型: 变量(variables) 和 网络(nets) ,包含4个状态值:0,1,Z,X。 变量(variables)的几种类型 1.无符号单bit或多bit变量 — reg [7:0] sum 2.有符号32bit — integer i 3.无符号64bit — time t 4.浮点数 — real r          SystemVerilog向Verilog语言添加了

    2024年02月06日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包