1029 Lost Cows 思维 树状数组 二分 前面有多少个数比自己小求出实际串
链接:https://ac.nowcoder.com/acm/contest/26896/1029
来源:牛客网
题目描述
N (2≤N≤8,000)(2 \leq N \leq 8,000)(2≤N≤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.
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.
分析
输入一组数据,每个数表示前面有多少个比自己小的。求出目标序列
原序列:0 1 2 1 0 目标序列: 2 4 5 3 1。
从最后一个开始考虑。
第n 个前面有0个比自己小的,因为没有任何数被排除,所以只能是1。
第n -1个前面有1个比自己小的,因为1被排除,所以只能是3。
第n -2个前面有2个比自己小的,因为1和3被排除,所以只能是5。
......
第1个前面有0个比自己小的,1 3 4 5 都被排除,所以只能是2
所以需要找到自己是还没被排除的数里的第几个
换言之找到有多少个数被排除了。在里面选出第a[i] 个
可以把剩余的数看作一个数组,如果还没被选,数组值就是1,被选择了,数组值就是0
将数组累加,直到累加到a[i] 就说明是没被选择的第a[i] 个
动态的区间和以及单点修改操作,考虑树状数组,二分找出sum值等于a[i] 的位置。
//-------------------------代码---------------------------- //#define int ll const int N = 1e5+10; int n,m; // 240/40=6 int a[N],b[N],p[N],tr[N]; void add(int x,int c) { for(int i = x;i<N;i+=lowbit(i)) tr[i] += c; } int sum(int x) { int res = 0;for(int i = x;i;i-=lowbit(i)) res += tr[i];return res; } void solve() { // cin>>n>>m; cin>>n; a[1] = 0;add(1,1); fo(i,2,n) { cin>>a[i]; add(i,1); } of(i,n,1) { // dbbb(i,a[i]+1,sum(a[i]+1)); // b[i] = sum(a[i]+1)+1+a[i]; // add(b[i],1); int l = 1,r = n; while(l < r) { int mid = l +r >> 1; if(sum(mid) >= a[i] + 1) r = mid ; else l = mid + 1; } b[i] = l; add(b[i],-1); } fo(i,1,n) cout<<b[i]<<'\n'; } void main_init() {} signed main(){ AC();clapping();TLE; cout<<fixed<<setprecision(12); main_init(); // while(cin>>n,n) // while(cin>>n>>m,n,m) // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------