K-th Closest Distance【主席树+二分答案】

HDU-6621 杭电2019多校


  区间询问,问的是【l,r】区间内的与P第K接近的数和P的大小差距。

  然后就是去维护一下区间的数量的和,然后我们不断的【p-mid,p+mid】的数的个数,当个数“≥K”的时候,就是我们所要的答案了。然后,我们就去二分答案这个mid就可以了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e5 + 7, _UP = 1e6;
int N, M, a[maxN], root[maxN*10], tot, lc[maxN*300], rc[maxN*300], val[maxN*300];
void Insert(int &now, int old, int l, int r, int x)
{
    now = ++tot; lc[now] = lc[old]; rc[now] = rc[old]; val[now] = val[old] + 1;
    if(l == r) return;
    int mid = (l + r)>>1;
    if(x <= mid) Insert(lc[now], lc[old], l, mid, x);
    else Insert(rc[now], rc[old], mid + 1, r, x);
}
int query(int p1, int p2, int l, int r, int ql ,int qr)
{
    if(ql <= l && qr >= r) return val[p2] - val[p1];
    int mid = HalF;
    if(qr <= mid) return query(lc[p1], lc[p2], l, mid, ql, qr);
    else if(ql > mid) return query(rc[p1], rc[p2], mid + 1, r, ql, qr);
    else return query(lc[p1], lc[p2], l, mid, ql, qr) + query(rc[p1], rc[p2], mid + 1, r, ql, qr);
}
inline void init()
{
    tot = 0;
    lc[0] = rc[0] = val[0] = 0;
}
int main()
{
    int Cas; scanf("%d", &Cas);
    while(Cas--)
    {
        scanf("%d%d", &N, &M);
        init();
        for(int i=1; i<=N; i++)
        {
            scanf("%d", &a[i]);
            Insert(root[i], root[i-1], 1, _UP, a[i]);
        }
        int l, r, p, K, ans = 0;
        while(M--)
        {
            scanf("%d%d%d%d", &l, &r, &p, &K);
            l = l ^ ans; r = r ^ ans; p = p ^ ans; K = K ^ ans;
            int L = 0, R = _UP, mid = 0;
            while(L <= R)
            {
                mid = (L + R)>>1;
                if(query(root[l-1], root[r], 1, _UP, p - mid, p + mid) >= K)
                {
                    R = mid - 1;
                    ans = mid;
                }
                else
                {
                    L = mid + 1;
                }
            }
            printf("%d\n", ans);
        }
    }
}
/*
1
7 1
1 1 1 2 2 5 5
1 7 2 4
ans:1
 
1
7 1
2 5 9 12 15 91 100
1 7 56 1
ans:35
*/

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个基于 Python 的 K-Means++ 类的示例代码: ```python import numpy as np class KMeansPP: def __init__(self, k): self.k = k def fit(self, X): n_samples, n_features = X.shape # Initialize centroids list and add the first random centroid centroids = [X[np.random.randint(n_samples)]] # Add remaining k-1 centroids for i in range(1, self.k): # Initialize distances list distances = [] for j in range(n_samples): # Compute distance between each sample and the nearest centroid min_dist = np.inf for centroid in centroids: dist = np.linalg.norm(X[j] - centroid) min_dist = min(min_dist, dist) distances.append(min_dist) # Add a new centroid randomly based on the distance weights distances_sum = sum(distances) distances = [dist / distances_sum for dist in distances] new_centroid = X[np.random.choice(n_samples, p=distances)] centroids.append(new_centroid) self.centroids = centroids # Perform K-Means clustering clusters = [[] for _ in range(self.k)] for sample in X: distances = [np.linalg.norm(sample - centroid) for centroid in self.centroids] closest_centroid_idx = np.argmin(distances) clusters[closest_centroid_idx].append(sample) self.clusters = clusters ``` 这个类的主要功能是进行 K-Means++ 聚类,其中 `k` 是簇的数量,`X` 是形状为 `(n_samples, n_features)` 的输入数据。在 `fit` 方法中,它首先从输入数据中选择一个随机初始中心点,然后根据每个样本到最近中心点的距离选择下一个中心点,并重复此过程直到选择 `k` 个中心点。然后,它使用这些中心点对输入数据进行 K-Means 聚类,并将每个样本分配到最近的中心点的簇中。 `centroids` 和 `clusters` 属性分别存储所选的中心点和生成的簇。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值