W
e
l
c
o
m
e
: )

CF895B XK Segments 题解

CF895B XK Segments 题解

题目描述

CF895B XK Segments

题目解法

朴素想法

最简单的想法就是枚举二元组 \((i,j)\) 的第一项 \(i\),然后再枚举 \(j\),找到一个满足条件的 \(a_j\),然后更新答案。

很明显,该做法的时间复杂度为 \(O(n^2)\),无法通过本题。

二分

我们发现,\(a\) 数组不会更改,并且每次枚举 \(a_j\) 的过程相当于查找符合条件的区间中元素的个数。

先算出大于等于 \(a_i\) 的第一个 \(x\) 的倍数 \(a_i\)

\[\begin{cases} a_i'=(\lfloor \frac{a_i}{x} \rfloor + 1)\times x & (a_i \not\equiv 0 \mod x)\\ a_i'=a_i & (a_i \equiv 0 \mod x) \end{cases} \]

符合条件的区间的左端点 \(l=a_i'+(k-1)\times x\)

符合条件的区间的右端点 \(r=a_i'+k\times x\)

记得特判 \(k=0\) 的情况。

先排序再二分端点,迭代器相减即可。

记得开 long long

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long

int n, x, k;
vector<int> vc;

signed main()
{
    cin>>n>>x>>k;
    int ans=0;
    for(int i=1, v;i<=n;i++)
        cin>>v, vc.push_back(v);
    sort(vc.begin(), vc.end());
    for(auto i:vc)
    {
        int nx=(i%x)?(i/x+1)*x:i;
        int l=k?nx+(k-1)*x:i, r=nx+k*x;
        auto it1=lower_bound(vc.begin(), vc.end(), r);
        auto it2=lower_bound(vc.begin(), vc.end(), l);
        ans+=it1-it2;
    }
    cout<<ans;
}
posted @ 2024-08-25 20:55  Jimmy-LEEE  阅读(13)  评论(0)    收藏  举报