区间查询问题

问题:In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in the famous novel Water Margin, you will win an amazing award.

As a smart boy, you notice that to win the award, you must buy much more snacks than it seems to be. To convince your friends not to waste money any more, you should find the expected number of snacks one should buy to collect a full suit of cards.
 
Input
The first line of each test case contains one integer N (1 <= N <= 20), indicating the number of different cards you need the collect. The second line contains N numbers p1, p2, ..., pN, (p1 + p2 + ... + pN <= 1), indicating the possibility of each card to appear in a bag of snacks.

Note there is at most one card in a bag of snacks. And it is possible that there is nothing in the bag.
 
Output
Output one number for each test case, indicating the expected number of bags to buy to collect all the N different cards.

You will get accepted if the difference between your answer and the standard answer is no more that 10^-4.
 

Sample Input
1
0.1
2
0.1 0.4

Sample Output
10.000
10.500

回答:题意:
给你 n个点。他们有 上下级关系,一个点只有一个上级,一个上级 可以有多个下级,每个点有两个属性,能力值 、忠诚度(每个节点的忠诚度不同),求我们要删除 一个节点, 则我们 需从 其下级中选出 一个节点,其能力值 比该节点 要高,且忠诚度是(比其能力高的下级节点中的)最高
题解:
首先将树状结构,转化为线状结构,
可以遍历一遍将树上每个点标记为一维区间上的某个点,且在同一棵子树内的点是连续的一段。
然后,将所有点按能力从大到小排序,能力相同的编号小的排在前面,然后扫描一遍,扫描时维护一颗线段树,
(我们先插入线段树的是,比其能力值 大的,我们只要从这些里面找到,忠诚度最高的就可以了)
先查找该点为根节点的子树内的最优值,然后插入该点的忠诚度。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define maxn    100110
#define mod 100000007
#define eps  1e-6;
#define ll  long long
#define M   15520
using namespace std;
map<int,int>map1;
vector<int>g[maxn] ;
int num ,ans[maxn],n,m,l[maxn],r[maxn];
struct staff
{
    int loy;
    int abt;
    int id;
}sta[maxn];
struct node
{
    int l;
    int r;
    int mx;
}p[maxn * 2];
bool cmp (staff a, staff b)
{
    return a.abt > b.abt ;
}
void dfs(int x)//编号变为线状结构
{
    l[x] = num++;
    for(int i = 0; i < g[x].size(); ++i)
    {
        dfs(g[x][i]);
    }
    r[x] = num ;
}
void build(int x,int l,int r)
{
    p[x].l = l;
    p[x].r = r;
    p[x].mx = -1 ;
    if(l == r) return  ;
    int mid = (l + r) /2;
    build(x*2,l,mid);
    build(x*2+1,mid + 1,r);
}
int get(int x,int l,int r)
{
    if( r < l ) return  -1 ;
    if(p[x].l == l && p[x].r == r)
    {
        return p[x].mx;
    }
    int mid = (p[x].l + p[x].r) /2 ;
    if(r <= mid)  return get(x * 2,l,r);
    else
    {
        if(l > mid) return get(x * 2 + 1,l,r);
        else
        {
            return max(get(x * 2,l,mid),get(x * 2 + 1,mid + 1,r));
        }
    }
}
void insert(int x,int pos,int d)
{
    if(p[x].l == p[x].r )
    {
        p[x].mx = d;
        return ;
    }
    int mid = (p[x].l + p[x].r) /2 ;
    if(pos <= mid) insert(x*2,pos,d);
    else
    {
        insert(x*2 + 1, pos,d);
    }
    p[x].mx = max(p[x*2].mx,p[x*2+1].mx);
}
void init()
{
    for( int i = 0; i <= n; ++i )
        g[i].clear();
    map1.clear();
    num = 0 ;
}
int main()
{
    int t,u,loy,abt,a,j,i;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init();
        for( i = 1 ; i < n; ++i)
        {
            scanf("%d%d%d",&u,&loy,&abt);
            g[u].push_back(i);
            sta[i].loy = loy;
            sta[i].abt = abt ;
            sta[i].id = i;
            map1[loy] = i;
        }
        dfs(0);
        build(1,0,num - 1);
        sort(sta + 1,sta + n,cmp);//排序为了下面 查询 打基础,排好序之后,我们插入时,保证了,比 i 大的已经插入了这时直接找,忠诚的uida就可以了
        for( i = 1 ; i < n ; i = j)
        {
            j = i;
            while(j < n &&sta[i].abt == sta[j].abt)
            {
                int id = sta[j].id ;
                loy = get(1,l[id] + 1,r[id] - 1);

                if(loy != -1) ans[id] = map1[loy] ;
                else ans[id] = -1;
                ++j;
            }
            j = i ;
            while(j < n && sta[i].abt == sta[j].abt )
            {
                int id =  sta[j].id;
                insert(1,l[id],sta[j].loy);
                ++j;
            }
        }
        while(m--)
        {
            scanf("%d",&a);
            printf("%d ",ans[a]) ;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/benchao/p/4541459.html