题目链接

题目

题目描述

\(N (2 \leq N \leq 8,000)\) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood 'watering hole' and drank a few too many beers before dinner. When it was time to line up for their evening meal, they did not line up in the required ascending numerical order of their brands.

Regrettably, FJ does not have a way to sort them. Furthermore, he's not very good at observing problems. Instead of writing down each cow's brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than that cow.

Given this data, tell FJ the exact ordering of the cows.

输入描述

  • Line 1: A single integer, N
  • Lines 2..N: These N-1 lines describe the number of cows that precede a given cow in line and have brands smaller than that cow. Of course, no cows precede the first cow in line, so she is not listed. Line 2 of the input describes the number of preceding cows whose brands are smaller than the cow in slot #2; line 3 describes the number of preceding cows whose brands are smaller than the cow in slot #3; and so on.

输出描述

  • Lines 1..N: Each of the N lines of output tells the brand of a cow in line. Line #1 of the output tells the brand of the first cow in line; line 2 tells the brand of the second cow; and so on.

示例1

输入

5
1
2
1
0

输出

2
4
5
3
1

题解

知识点:树状数组,倍增,枚举。

首先需要一个事实,对于一个排列,要确定其中某个位置的数具体是多少,可以通过整个排列比它小的数字有多少个(或者比它大的数字有多少个)确定。现在这道题确定了各个位置的数的左边比它小的数的个数,我们只需要知道在它右边有多少个数比它小就行,因此我们从右往左枚举,依次确定数字。

首先用树状数组维护右侧出现的数字,随后需要二分一个 \(x\) 通过比较 \(x - cnt_{<x} -1 < a_i\) 得知 \(x\) 是否小了还是大了,从而找到第一个 \(x - cnt_{<x} -1 = a_i\) 的点。注意,条件不能为 \(x - cnt_{<x} -1 \leq a_i\) , 因为可能会出现连续一段刚好等于 \(a_i\) 的点,而我们只需要第一个的下标即可,如果用这个条件,我们得到的是最后一个下标。

当然,这个二分条件其实还可以更简单,我们反过来记录右侧没出现的数字,那么 \(cnt_{<x}\) 直接代表左侧比 \(x\) 小的数字个数,那么条件为 \(cnt_{<x} < a_i\) 即可。

另外,二分套树状数组查询的复杂度是对数平方的,并不是最优的。我们可以直接使用树状数组本身的倍增性质进行二分,是最优的对数复杂度。我封装了两个常用的函数,大于等于 lower_bound 和大于 upper_bound

这道题查询 \(cnt_{<x} = a_i\) 的第一个点,我们 lower_bound 查询即可。

时间复杂度 \(O(n \log n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; template <class T>
class Fenwick {
int n;
vector<T> node; public:
Fenwick(int _n = 0) { init(_n); } void init(int _n) {
n = _n;
node.assign(n + 1, T());
} void update(int x, T val) { for (int i = x;i <= n;i += i & -i) node[i] += val; } T query(int x) {
T ans = T();
for (int i = x;i >= 1;i -= i & -i) ans += node[i];
return ans;
}
T query(int l, int r) { return query(r) - query(l - 1); } int lower_bound(T val) {
int pos = 0;
for (int i = 1 << __lg(n); i; i >>= 1) {
if (pos + i <= n && node[pos + i] < val) {
pos += i;
val -= node[pos];
}
}
return pos + 1;
}
int upper_bound(T val) {
int pos = 0;
for (int i = 1 << __lg(n); i; i >>= 1) {
if (pos + i <= n && node[pos + i] <= val) {
pos += i;
val -= node[pos];
}
}
return pos + 1;
}
}; int a[8007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 2;i <= n;i++) cin >> a[i];
Fenwick<int> fw(n);
for (int i = 1;i <= n;i++) fw.update(i, 1); vector<int> ans(n + 1);
for (int i = n;i >= 1;i--) {
ans[i] = fw.lower_bound(a[i] + 1);
fw.update(ans[i], -1);
}
for (int i = 1;i <= n;i++) cout << ans[i] << '\n';
return 0;
}

NC51101 Lost Cows的更多相关文章

  1. [LeetCode] Bulls and Cows 公母牛游戏

    You are playing the following Bulls and Cows game with your friend: You write a 4-digit secret numbe ...

  2. POJ 2186 Popular Cows(Targin缩点)

    传送门 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31808   Accepted: 1292 ...

  3. POJ 2387 Til the Cows Come Home(最短路 Dijkstra/spfa)

    传送门 Til the Cows Come Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 46727   Acce ...

  4. LeetCode 299 Bulls and Cows

    Problem: You are playing the following Bulls and Cows game with your friend: You write down a number ...

  5. [Leetcode] Bulls and Cows

    You are playing the following Bulls and Cows game with your friend: You write a 4-digit secret numbe ...

  6. 【BZOJ3314】 [Usaco2013 Nov]Crowded Cows 单调队列

    第一次写单调队列太垃圾... 左右各扫一遍即可. #include <iostream> #include <cstdio> #include <cstring> ...

  7. POJ2186 Popular Cows [强连通分量|缩点]

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31241   Accepted: 12691 De ...

  8. Poj2186Popular Cows

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31533   Accepted: 12817 De ...

  9. [poj2182] Lost Cows (线段树)

    线段树 Description N (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacula ...

  10. 【POJ3621】Sightseeing Cows

    Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8331   Accepted: 2791 ...

随机推荐

  1. Hadoop服务启动失败

    Hadoop服务启动失败今天启动Hadoop时,终端报了一个新的错误 ```bashStarting namenodes on [192.168.19.128]192.168.19.128: ssh: ...

  2. promise一脸懵逼...

    // 要求:封装一个方法,能根据路径读取文件,并把内容返回 const fs=require('fs') const path=require('path') 1. 普通读取文件的方式 1 const ...

  3. MYSQL5.7实现递归查询

    根据父id查出所有子级,包括子级的子级,包括自身的id sys_tenant_company_relation为关联表, company_id为子id,parent_company_id为父id SE ...

  4. js对象深拷贝方法

    JSON.stringify()是目前前端开发过程中最常用的深拷贝方式, 原理是把有个对象序列化成为一个 JSON 字符串,将对象的内容转换成字符串的形式再保存到磁盘上, 再用 JSON.parse( ...

  5. Android笔记--Activity--启停活动页面

    Activity启动 从当前页面跳转到新的页面:startActivity(new Intent(原页面.this,目标页面.class)) 而若是从当前页面返回到上一个页面,相当于关闭当前页面,使用 ...

  6. mybatis-plus update的三种方式

    参考博客:https://blog.csdn.net/weixin_44162337/article/details/107828366 1.最常见:根据id更新,xxxService.updateB ...

  7. 服务器资源监测脚本(网卡、MEM、CPU)

    #-*- coding: utf-8 -*- #!/usr/bin/python ''' 用法: sar [ 选项 ] [ <时间间隔> [ <次数> ] ] 主选项和报告: ...

  8. 玩转SpringBoot原理:掌握核心技术,成为高级开发者

    本文通过编写一个自定义starter来学习springboot的底层原理,帮助我们更好的使用springboot集成第三方插件 步骤一:创建项目 步骤二:添加依赖 步骤三:创建自动配置类 步骤四:创建 ...

  9. 跨域解决方案CORS

    这里说的 js 跨域是指通过 js 在不同的域之间进行数据传输或通信,例如通过 ajax 向一个不同的域请求数据,或者通过 js 获取页面中不同域中(iframe)的数据.只要协议.域名.端口有任何一 ...

  10. openwrt 刷回梅林或者原厂固件

    路由器刷了openwrt固件后,访问不了CFE恢复模式了.本人最近用腾达AC18路由器,刷了AC68U的梅林改版固件.但是后面再用CFE刷了openwrt固件之后,发现wifi不能用,所以又想刷回梅林 ...