• 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;
    }
  • 相关阅读:
    python初接触
    Visual Studio Code 必备插件
    C# 基础知识 -- 枚举(Enum)
    Visual Studio : Console.WriteLine(); 快捷键
    C# 调用Outlook发送邮件
    C# Dos、Unix、Mac文件格式之间的相互转换
    Treeview控件失去焦点,将选择的节点设置为高亮显示
    oracle中的Exists、In、Any、All
    TreeView控件如何控制滚动条的位置
    oracle 查看最大连接数与当前连接数
  • 原文地址:https://www.cnblogs.com/rainydays/p/2007485.html
Copyright © 2020-2023  润新知