题目描述
有n头奶牛,已知它们的身高为 1~n 且各不相同,但不知道每头奶牛的具体身高。
现在这$n$头奶牛站成一列,已知第i头牛前面有$A_i$头牛比它低,求每头奶牛的身高。
输入格式
第1行:输入整数$n$。
第2..n行:每行输入一个整数$A_i$,第i行表示第i头牛前面有$A_i$头牛比它低。
(注意:因为第1头牛前面没有牛,所以并没有将它列出)
输出格式
输出包含$n$行,每行输出一个整数表示牛的身高。
第$i$行输出第$i$头牛的身高。
数据范围
$1≤n≤10^5$
样例
输入样例:
5
1
2
1
0
输出样例:
2
4
5
3
1
树状数组+二分
我们发现,如果说第$K$头牛的前面有$A_k$头牛比它矮,那么它的身高$H_k$就是数值$1~n$中第$A_k+1$小的没有在${H_{k+1},H_{k+2},…,H_n}$中出现过的数
所以说,我们需要建立一个长度为n的1序列b,刚开始都是1,然后n到1倒序扫描每一个$A_i$,对于每个$A_i$执行查询和修改操作.
也就是说这道题目的题意就是让我们,动态维护一个01序列,支持查询第k个1所在的位置,以及修改序列中的一个数值
C++ 代码
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
const int N=2e5;
int c[N],a[N],n,m,i,j,ans[N];
inline int ask(int x)
{
int ans=0;
for(;x;x-=lowbit(x))
ans+=c[x];
return ans;
}
inline int add(int x,int y)
{
for(;x<=n;x+=lowbit(x))
c[x]+=y;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
add(1,1);
for(i=2;i<=n;i++)
{
cin>>a[i];
add(i,1);
}
for(i=n;i>=1;i--)
{
int l=1,r=n;
while(l<r)//二分找点
{
int mid=l+r>>1;
if (ask(mid)<a[i]+1)//查询第A_{i}+1个1在什么位置,这个位置号就是奶牛的高度
l=mid+1;
else
r=mid;
}
ans[i]=r;
add(r,-1);//我们已经选择了
}
for(i=1;i<=n;i++)//倒序扫描,正序输出
cout<<ans[i]<<endl;
return 0;
}
数组为什么要开2e5
为什么初始化维护的数组时用memset(tr,1,sizeof tr),会出错;
#include[HTML_REMOVED]
#include[HTML_REMOVED]
using namespace std;
#define lowbit(x) x&-x
const int N = 1e5+10;
int f[N], tr[N], a[N];
int n;
void add(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
tr[i]+=k;
}
int sum(int x)
{
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=tr[i];
return ans;
}
int main()
{
}
memset是不能把int类型的数组所有元素都置位1的
唔我倒是瞎搞弄出来了另一个二分板子的ac代码,但是也有不懂的点,望大佬提点
https://www.acwing.com/problem/content/discussion/content/3376/
int mid = l+r+1>>1;
if(ask(mid)>a[i]+1)
r=mid-1;
else
l=mid;
这个板子就不行咋
m没有用定义干啥?
如果是无序的数组 查询第k大是不是就不能用vector了 可以用vector来查询第k大的前提是数组有序
感觉很多题解都有大佬的身影QwQ
谢谢大佬 大佬txdy
大佬求解 为什么这里二分用的是求后继的二分而不是求前驱的呢
大佬牛逼,看到你几次了,感谢!
int mid = l+r+1>>1;
if(ask(mid)>a[i]+1)
r=mid-1;
else
l=mid;
为什么向上取整就错了呢
同问!搞得我现在每次写题两个板子都要试试
带捞您真是高产
QwQ我还好吧.
还有二分后面那里,为什么是add(r,-1)啊QwQ
已经选择了,标记为-1,表示这头奶牛选择了,因为之前所有都+1,那么-1自然就是消失了。
1表示没有出现,0表示出现了,自然要跳过了。
哦哦哦我还以为-1是高度减一,原来是打标记啊谢谢大佬%%%
您客气了。
“如果说第K头牛的前面有Ak头牛比它矮,那么它的身高Hk就是数值 1 n 中第Ak+1小的没有在Hk+1,Hk+2,…,HnHk+1,Hk+2,…,Hn中出现过的数”,为什么是没有出现过的数啊,想不明白= =
肯定是没有出现过的数啊,出现过的,就是前面的每一头牛的身高,那么他是第$A_k+1$高的奶牛,所以自然就是这样了。