NKOJ 3709 走丢的奶牛 树状数组
题面:约翰有n头奶牛,这些奶牛长得很相似,约翰经常分不清谁是谁,于是约翰给他们编号1到n,以此来区分每头奶牛。
今天奶牛们想作弄一下约翰,n头奶牛乱序排成一排。
约翰想要分清每个位置对应奶牛的编号。约翰从左起第2头奶牛开始一直到第n头奶牛,依次问每个奶牛一个问题“你左边有多少个编号比你小的奶牛”,奶牛们都会如实回答约翰的问题。
问,你能否根据奶牛的回答,帮助约翰推出这n头牛对应的编号?
解法:首先维护一个树状数组来保存遇到的所有奶牛的编号,于是每次二分编号,如果右边遇到的比自己大的加上左边比自己大的大于这个编号就调小编号,反之调大编号。
#include <bits/stdc++.h> using namespace std; int a[100005], c[100005], n, b[100005]; void modify(int x, int p) { for (int i = x; i<= n; i += (i & (-i))) c[i] += p; } int query(int x) { int ans = 0; for (int i = x; i; i -= (i & (-i))) { ans += c[i]; } return ans; } int main() { // int n; scanf("%d", &n); for (int i = 2; i <= n; i++) { scanf("%d", &a[i]); } for (int i = n; i; i--) { int l = 1, r = n; while (l <= r) { int mid = (l + r) >> 1; if (query(mid) + a[i] < mid) r = mid - 1; else l = mid + 1; } b[i] = l; modify(l, 1); } for (int i = 1; i <= n; i++) { printf("%d\n", b[i]); } }

浙公网安备 33010602011771号