HDU 5493 Queue (线段树逐个插入)

参考博客:
http://blog.csdn.net/hyczms/article/details/48767933

题目链接:
http://acm.split.hdu.edu.cn/showproblem.php?pid=5493

题目大意:有n个人排队,每个人都有一个身高,每个人记得他前面或者后面可能有x个人比他高(满足一个就行),问能否有一个序列满足给出的条件,如果有,请让字典序最小,

解题思路:从前往后插,给n个位置赋值为0,每个人前面或者后面必须有x个0,找到满足条件的靠前的位置,赋值为其为第几个人,线段树维护区间0的个数,若找不到则无解。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <numeric>
#include <functional>
#define RI(N) scanf("%d",&(N))
#define RII(N,M) scanf("%d %d",&(N),&(M))
#define RIII(N,M,K) scanf("%d %d %d",&(N),&(M),&(K))
#define mem(a) memset((a),0,sizeof(a))
using namespace std;
const int inf=1e9;
const int inf1=-1*1e9;
double EPS=1e-10;
typedef long long LL;

int ans[100005];
int tre[100005<<2];
struct P
{
    int val;
    int poi;
};

bool cmp(P p1,P p2)
{
    return p1.val<p2.val;
}
void pushup(int rt)
{
    tre[rt]=tre[rt<<1]+tre[rt<<1|1];
}

void build(int l,int r,int rt)
{
    if(l==r)
    {
        tre[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
void update(int l,int r,int rt,int poi,int add)
{
    if(l==r)
    {
        ans[l]=add;
        tre[rt]=0;
        return ;
    }
    int m=(l+r)>>1;
    if(poi<=tre[rt<<1]) update(l,m,rt<<1,poi,add);
    else update(m+1,r,rt<<1|1,poi-tre[2*rt],add);
    pushup(rt);
}

P p[100005];

int main()
{
    int T,cas=1;
    RI(T);
    while(T--)
    {
        int n;
        RI(n);
        for(int i=0;i<n;i++)
        {
            RII(p[i].val,p[i].poi);
        }
        sort(p,p+n,cmp);
        bool mark=true;
        build(1,n,1);
       // cout<<tre[1]<<" "<<tre[2]<<" "<<tre[3]<<endl;
        for(int i=0;i<n;i++)
        {
            int t=p[i].poi;
            int rem=n-i;
            if(t>=rem)
            {
                mark=false;
                break;
            }
            if(n-i-t>t+1) {
                    update(1,n,1,t+1,p[i].val);
                //cout<<"t+1 = "<<t+1<<endl;
            }
            else {
                   // cout<<"n-i-t+1 = "<<n-i-t+1<<endl;
                    update(1,n,1,n-i-t,p[i].val);
            }
        }
        if(mark)
        {
            printf("Case #%d:",cas++);
            for(int i=1;i<=n;i++)
                printf(" %d",ans[i]);
            printf("\n");

        }
        else printf("Case #%d: impossible\n",cas++);

    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值