zoukankan      html  css  js  c++  java
  • poj2761

    题意:给出每只狗的pretty value,然后多次询问,每次输出区间[i,j](狗站成一排,从第i只到第j只)的第k小的值是多少。区间之间有交叉,但是没有完全包含。

    分析:先把所有区间排序,然后从左至右把每个区间用线段树维护离散化后的pretty value,即线段树的区间的意义是pretty value。每次删除在上一个区间中且不在当前区间中的节点,插入在当前区间中且不在上一个区间中的节点,使得线段树中的节点恰好为该区间内的所有节点。然后查询第k个就容易了。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    #include
    <algorithm>
    usingnamespace std;

    #define maxn 100005
    #define maxm 50005

    struct Interval
    {
    int s, e, k, pos, ans;
    }interval[maxm];

    struct Node
    {
    Node
    *pleft, *pright;
    int l, r;
    int num;
    }tree[maxn
    *3];

    int dog[maxn], n, m, pretty[maxn], opdog[maxn], ncount;

    booloperator< (const Interval &a, const Interval &b)
    {
    if (a.s != b.s)
    return a.s < b.s;
    return a.e < b.e;
    }

    bool cmp(const Interval &a, const Interval &b)
    {
    return a.pos < b.pos;
    }

    int binarysearch(int a)
    {
    int l =0;
    int r = n -1;
    int mid = (l + r) /2;
    while (l < r)
    {
    if (pretty[mid] < a)
    l
    = mid +1;
    else
    r
    = mid;
    mid
    = (l + r) /2;
    }
    return l;
    }

    void buildtree(Node *proot, int l, int r)
    {
    proot
    ->l = l;
    proot
    ->r = r;
    proot
    ->num =0;
    if (l == r)
    return;
    int mid = (l + r) /2;
    ncount
    ++;
    proot
    ->pleft = tree + ncount;
    ncount
    ++;
    proot
    ->pright = tree + ncount;
    buildtree(proot
    ->pleft, l, mid);
    buildtree(proot
    ->pright, mid +1, r);
    }

    void ins(Node *proot, int a, int d)
    {
    proot
    ->num += d;
    if (proot->l == proot->r)
    return;
    int mid = (proot->l + proot->r) /2;
    if (a <= mid)
    ins(proot
    ->pleft, a, d);
    else
    ins(proot
    ->pright, a, d);
    }

    int query(Node *proot, int k)
    {
    if (proot->l == proot->r)
    return pretty[proot->l];
    if (proot->pleft->num >= k)
    return query(proot->pleft, k);
    else
    return query(proot->pright, k - proot->pleft->num);
    }

    void input()
    {
    scanf(
    "%d%d", &n, &m);
    for (int i =0; i < n; i++)
    {
    scanf(
    "%d", &dog[i]);
    pretty[i]
    = dog[i];
    }
    for (int i =0; i < m ; i++)
    {
    scanf(
    "%d%d%d", &interval[i].s, &interval[i].e, &interval[i].k);
    interval[i].s
    --;
    interval[i].e
    --;
    interval[i].pos
    = i;
    }
    }

    void work()
    {
    for (int i = interval[0].s; i <= interval[0].e; i++)
    ins(tree, dog[i],
    1);
    interval[
    0].ans = query(tree, interval[0].k);
    for (int i =1; i < m; i++)
    {
    for (int j = interval[i -1].s; j <= min(interval[i -1].e, interval[i].s -1); j++)
    ins(tree, dog[j],
    -1);
    for (int j = max(interval[i -1].e +1, interval[i].s); j <= interval[i].e; j++)
    ins(tree, dog[j],
    1);
    interval[i].ans
    = query(tree, interval[i].k);
    }
    }

    int main()
    {
    //freopen("D:\\t.txt", "r", stdin);
    input();
    sort(interval, interval
    + m);
    sort(pretty, pretty
    + n);
    for (int i =0; i < n; i++)
    {
    dog[i]
    = binarysearch(dog[i]);
    opdog[dog[i]]
    = i;
    }
    ncount
    =0;
    buildtree(tree,
    0, n -1);
    work();
    sort(interval, interval
    + m, cmp);
    for (int i =0; i < m; i++)
    printf(
    "%d\n", interval[i].ans);
    return0;
    }
  • 相关阅读:
    linux内核中GNU C和标准C的区别
    linux内核中GNU C和标准C的区别
    Getting start with dbus in systemd (02)
    Getting start with dbus in systemd (01)
    Getting start with dbus in systemd (03)
    物理内存相关的三个数据结构
    数据类型对应字节数(32位,64位 int 占字节数)
    Linux kernel 内存
    共模电感的原理以及使用情况
    [原创]DC-DC输出端加电压会烧毁
  • 原文地址:https://www.cnblogs.com/rainydays/p/2007485.html
Copyright © 2011-2022 走看看