最后一次新生排位赛

第十二次新生排位赛

第一题

  1. Study sister's barbarian
    时间限制 2000 ms 内存限制 65536 KB
    题目描述
    Study sister plays the game coc everyday. When she wants to attack another clan, Study brothers will donate a lot of barbarian to help her.
    We assume that there are n Study brothers and each of them send one barbarian to help Study sister. The barbarians had different hitpoints, and they had to stand in one line when they get out of the clan.
    Some Study brothers wants to impress Study sister, so they wants their own barbarian become the ai-th barbarian that get out of the clan. We know that Study brothers donate their barbarian in turn, so the order they choose when they donate the army may not be the final order. Now given the donating behavior in order, Study sister wants to know the final sequence of barbarian by their hitpoints.

输入格式
There are several test case. Each test case begin with a sigal integer n(1<=n<=200000), means the number of Study brothers. Next n line, each line contains two integer a, b, means the i-th Study brother wants his barbarian become the a-th army that get out of the clan, and its hitpoints is b. 0<=a<i, 0<=b<100000.

There are break line between each test case.

输出格式
For each case, print one line, the final sequence of barbarian by their hitpoints.

输入样例
4
0 77
1 51
1 33
2 69
输出样例
77 33 69 51

hint:
the process are:
a barbarian of 77 hitpoints wants to become the 0-th, now the sequence becomes: 77
a barbarian of 51 hitpoints wants to become the 1-th, now the sequence becomes: 77 51
a barbarian of 33 hitpoints wants to become the 1-th, now the sequence becomes: 77 33 51
a barbarian of 69 hitpoints wants to become the 2-th, now the sequence becomes: 77 33 69 51

这题是poj原题2828,可以用树状数组加二分来做,也可以用线段树来做,由于线段树已带二分性质,所以比线段树快了一半的时间 题目主要的一个思想是逆序思考。假设共有n个数,最后一个放进去的肯定放在他所指定i-th的位置,倒数第二个放在剩下的空格的第i-th,所以题目转变成了计算当前第i-th空格实际位置在哪里。可以预处理n个位置原来都是0, 放一个就是该位置变成1,某一个位置pos(包括它自己)前面的空格的个数就是pos - sum(pos);当然也可以预处理n个位置原来都是1, 放一个就是该位置-1变成0,某一个位置pos(包括它自己)前面的空格的个数就是sum(pos);strong text

c++
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;
int ans[200005];
int a[200005];
int b[200005];
int c[200005];
int n;
void update(int pos, int w)
{
    while(pos<=n)
    {
        c[pos] += w;
        pos += pos&-pos;
    }
}
int sum(int pos)
{
    int ans=0;
    while(pos)
    {
        ans+=c[pos];
        pos -= pos&-pos;
    }
    return ans;
}
int get(int pos)//二分查找位置
{
    int head=1;
    int last=n;
    int mid=(head+last)/2;
    int t=mid-sum(mid);
    while (t!=pos)
    {
        if (t>pos)
        {
            last = mid;
        }
        else head = mid+1;
        mid=(head+last)/2;
        t=mid-sum(mid);
    }
    return mid;
}

int main()
{
    while (~scanf("%d", &n))
    {
        int a1, b1;
        for (int i=1; i<=n; i++)
        {
            scanf("%d %d", &a1, &b1);
            a[i] = a1+1;
            b[i] = b1;
            c[i] = 0;
        }
        for (int i=n; i>0; i--)
        {
            int t = get(a[i]);
            while (ans[t]!=-1) t--;
            ans[t] = b[i];
            update(t, 1);
        }
        for (int i=1; i<=n; i++)
        {
            printf("%d", ans[i]);
            if (i<n) printf(" ");
        }
        printf("\n");

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值