现在的位置: 首页 > 综合 > 正文

hdu 5021 Revenge of kNN II(树状数组)

2018年04月03日 ⁄ 综合 ⁄ 共 1402字 ⁄ 字号 评论关闭

hdu 5021 Revenge of kNN II

题解中提到需要用到二分,即对于每个点Q二分枚举距离x,使在区间[Q-x, Q+x]的点刚好为k个。
若对于距离x,所处区间内的点数为k或者k+1(在满足题意的情况下可去掉一个点使数目变为k),则可退出查找。
至于区间更新和查询明显要用到树状数组
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
typedef __int64 LL;
const int MAXN = 100005;
int n, m, mmp[MAXN];
struct _node
{
    int idx, x;
    double v;
    bool operator < (const _node & a) const
    {
        return x < a.x;
    }
}da[MAXN];
double res[MAXN];
int low_bit(int x)
{
    return x&(-x);
}
void add(int x, double v)
{
    while (x<= n)
    {
        res[x] += v;
        x += low_bit(x);
    }
}
double getsum(int x)
{
    double sum = 0.0;
    while (x >= 1)
    {
        sum += res[x];
        x -= low_bit(x);
    }
    return sum;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int t;
    int q, k, p, bg, ed, md, o, a, b;
    double ot;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m);
        ot = 0.0;
        for (int i = 1; i<= n; ++i)
        {
            scanf("%d%lf", &da[i].x, &da[i].v);
            da[i].idx = i;
            res[i] = 0.0;
        }
        sort(da+1, da+n+1);
        for (int i = 1; i<= n; ++i) mmp[da[i].idx] = i;
        for (int i = 1; i<= n; ++i)
            add(i, da[i].v);
        while (m--)
        {
            _node co;
            scanf("%d%d", &q, &k);
            p = mmp[q];
            bg = 1, ed = 1000000005;
            while (bg <= ed)
            {
                md = (bg+ed)>>1;
                co.x = da[p].x - md;
                a = lower_bound(da+1, da+n+1, co)-da;
                co.x = da[p].x + md;
                b = upper_bound(da+1, da+n+1, co)-da-1;
                o = b-a;
                if (o < k) bg = md+1;
                else if (o == k) break;
                else if (o == k+1)
                {
                    if (da[p].x - da[a].x == da[b].x - da[p].x)
                    {
                        if (da[a].idx < da[b].idx) --b;
                        else ++a;
                        break;
                    }
                    else ed = md-1;
                }
                else ed = md-1;
            }
            double s1 = getsum(b) - getsum(a-1) - da[p].v;
            add(p, s1/k - da[p].v);
            ot += (da[p].v = s1/k);
        }
        printf("%.3lf\n", ot);
    }
    return 0;
}
【上篇】
【下篇】

抱歉!评论已关闭.