Fenwick 树状数组上二分

其实应该叫倍增。

由于这篇文章中 lowbit 估计不少,所以一律用 low

Acwing244. 谜一样的牛

给定一个长度 n105 序列,求逆康托。

0ai<i

若是 logn 二分,再 logn Fenwick,O(nlog2n) 要跑 600ms,数据加强一下就过不了。

若是 logn 在线段树上二分,常数过大。

所以我们就请出了主题——树状数组上二分

原理是位置 x 存的是x 为右端点长度为 low(x) 区间信息

由于 low(x) 都是 2 的幂,所以就是倍增的料!

不管了,好像代码更能让你懂。

/*
* Author: ShaoJia
* Last Modified time: 2022-09-26 19:47:51
* Motto: We'll be counting stars.
*/
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define For(i,j,k) for(int i=(j),i##_=(k);i<=i##_;i++)
#define Rof(i,j,k) for(int i=(j),i##_=(k);i>=i##_;i--)
const int N=1e5+5;
int n,a[N],c[N],b[N];
inline int low(int x){ return x&(-x); }
void add(int x,int y){ while(x<=n) c[x]+=y,x+=low(x); }
int jump(int x){//the last pos that presum<=x
int pos=0,sum=0,np;
Rof(i,20,0)
if((np=pos|(1<<i))<=n && sum+c[np]<=x)
sum+=c[np],pos=np;
return pos;
}
signed main(){ios::sync_with_stdio(false),cin.tie(nullptr);
cin>>n;
For(i,2,n) cin>>a[i];
For(i,1,n) c[i]=low(i);
Rof(i,n,1) b[i]=jump(a[i])+1,add(b[i],-1);
For(i,1,n) cout<<b[i]<<"\n";
return 0;}

P6619 [省选联考 2020 A/B 卷] 冰火战士

代码和题解都贺。

题解

Link

posted @   ShaoJia  阅读(419)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示