hdu 5493 (树状数组)

题意:在一个队列中,你知道一个人在他左边或者右边比他高的人的个数,求字典序最小的答案

思路:先将人按  矮-->高 排序,然后算出在每个人前面需要预留的位置。树状数组(也可以线段树)解决时,先二分查找合适的位置,如果合理则标记,每次查找时    枚举的人数 - 前面已占的人数 = 可预留位置

判断分别在它左边 或者 右边时可能的最小值进行比较。

预留的位置①:pnode[i].num(即比他高的人数,全在左) 

                  ②:n - ( pnode[i].num + i) (当比他高,和前面加入的全在右边时) //为了字典序最小


/* 当时是一点头绪都没有- -,没想到是可以用线段树和二维数组,果然太年轻


#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 100010
using namespace std;

const int N = 1e5 + 5;
int n,m;
int tree[N];
struct node
{
    int id,num,position;
}pnode[N];

bool cmp(node a,node b)
{
        return a.id < b.id;
}
bool cmp2(node a,node b)
{
        return a.position < b.position;
}

void add(int x , int dx)
{
    while(x < N)
    {
        tree[x] += dx ;
        x += x&(-x) ;
    }
}
int query(int x)
{
    int sum = 0 ;
    while(x)
    {
        sum += tree[x] ;
        x -= x&(-x) ;
    }
    return sum ;
}

int fin(int l,int r,int x)
{
    if(x < 0)
        return -1;
    while(l <= r)
    {
        int mid = (l + r)/2;
        int tt= mid - query(mid);  //找出前面有多少空位
        if(tt < x)
            l  =mid + 1;
        else
            r = mid - 1;
    }
    return l;
}

void ini()
{
    for(int i = 0;i <= n;i++)
        tree[i] = 0;
}

int main()
{
    int t,cas = 1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);

        for(int i = 1;i <= n;i++)
            scanf("%d%d",&pnode[i].id,&pnode[i].num);
        sort(pnode+1,pnode+1+n,cmp);
        ini();
        int flag = 0;
        for(int i = 1;i <= n;i++)
        {
            int p = n - (i - 1) ;         //求还剩下多少位置
            int tp = pnode[i].num;        
            if(p <= tp)                   //判断剩下的能否预留合理位置
                flag = true;
            int x1 = fin(1,n,pnode[i].num + 1);
            int x2 = fin(1,n,n -pnode[i].num-i + 1);
            pnode[i].position = min(x1,x2);
            add(pnode[i].position,1);
        }

       printf("Case #%d: ", cas++);
       if(flag )
       {
           printf("impossible
");
           continue;
       }
       sort(pnode+1,pnode+n+1,cmp2);
        printf("%d", pnode[1].id);
        for (int i = 2; i <= n; i++)
            printf(" %d", pnode[i].id);
        printf("
");

    }
    return 0;
}

  

ps.如果没有东西值得你为之努力,那你和一条咸鱼有什么区别? 






原文地址:https://www.cnblogs.com/Przz/p/5409741.html