数据结构学习——动态逆序对
来源:互联网 发布:沅有芷兮澧有兰 知乎 编辑:程序博客网 时间:2024/06/07 19:27
解法一: 分块套BIT
利用树状数组算最初的逆序对个数
利用树状数组算出块中比x小的数的个数
遍历x所在的那个块
总复杂度O(
S取
#include<cstdio>#include<cmath>#include<algorithm>using namespace std;#define M 100005#define N 80int A[M],C[M],Cnt[N];int n,m,S,G;struct BIT{ int Sum[M]; void update(int x,int a){ while(x<=n)Sum[x]+=a,x+=x&(-x); } int query(int x){ int ans=0; while(x)ans+=Sum[x],x-=x&(-x); return ans; }}Bit[N];long long Query(int x){ long long cnt=0; int now=(C[x]-1)/S+1; for(int i=1;i<now;i++)cnt+=Cnt[i]-Bit[i].query(x); for(int i=now+1;i<=G;i++)cnt+=Bit[i].query(x); for(int i=(now-1)*S+1;i<=min(n,now*S);i++){ if(A[i]==0)continue; if((A[i]>x&&i<C[x])||(A[i]<x&&i>C[x]))cnt++; } return cnt;}void Update(int x){ A[C[x]]=0; int now=(C[x]-1)/S+1; Cnt[now]--; Bit[now].update(x,-1);}int main(){ long long ans=0; scanf("%d%d",&n,&m); S=sqrt(n*log2(n)); G=(n-1)/S+1; for(int i=1;i<=n;i++){ scanf("%d",&A[i]),C[A[i]]=i; ans+=i-Bit[0].query(A[i])-1; Bit[0].update(A[i],1); } for(int i=1;i<=G;i++) for(int j=i*S-S+1;j<=min(i*S,n);j++) Bit[i].update(A[j],1),Cnt[i]++; for(int i=1;i<=m;i++){ int x; scanf("%d",&x); printf("%lld\n",ans); Update(x); ans-=Query(x); } return 0;}
解法二:BIT套BIT
类似于分块
第一层的BIT就是代替分块的功能
但使用BIT的复杂度会比分块小很多 理解也难了很多
第一层的BIT对应的是下标,第二层的BIT是第一层所管辖到的子树
第二层负责维护信息,第一层负责映射出要查询的东西
可以说要更新一个值,先去找第一层
然后第一层再找第二层
可以说更新的永远是第二层
第一层只负责反馈和指挥第二层
代码实现:
#include<cstdio>#include<algorithm>#include<vector>using namespace std;#define M 100005#define pb push_back#define ll long longint A[M],W[M];int n,m;struct NODE{ int Sum[M]; void insert(int x){ while(x<=n){ Sum[x]++; x+=x&-x; } } ll query(int x){ ll ans=0; while(x){ ans+=Sum[x]; x-=x&-x; } return ans; } ll solve(){ ll ans=0; for(int i=1;i<=n;i++){ ans+=i-query(A[i])-1; insert(A[i]); } return ans; }}KG;struct node{ vector<int>val; vector<int>num; int sz; void init(){ sort(val.begin(),val.end()); sz=val.size()-1; //erase(unique(val.begin(),vel.end()),val.end()); for(int i=1;i<=sz;i++){ num.pb(i&-i); } } void update(int x){ int k=lower_bound(val.begin(),val.end(),x)-val.begin();//从该点开始更新 while(k<(int)val.size()){ num[k]--; k+=k&-k; } sz--; } ll query(int x){ ll ans=0; int k=lower_bound(val.begin(),val.end(),x)-val.begin()-1;//从该点前一点查询 while(k){ ans+=num[k]; k-=k&-k; } return ans; }}C[M];ll Getsize(int x){ ll sum=0; while(x){ sum+=C[x].sz; x-=x&-x; } return sum;}ll Getsum(int x,int val){ ll sum=0; while(x){ sum+=C[x].query(val); x-=x&-x; } return sum;}void Init(){ for(int i=0;i<=n;i++)C[i].val.pb(0),C[i].num.pb(0); for(int i=1;i<=n;i++){ int x=i; while(x<=n){ C[x].val.pb(A[i]); x+=x&-x; } }}void Del(int x,int val){ while(x<=n){ C[x].update(val); x+=x&-x; }}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&A[i]); W[A[i]]=i; } Init(); for(int i=1;i<=n;i++)C[i].init(); long long tmp=KG.solve(); for(int i=1;i<=m;i++){ int x; scanf("%d",&x); printf("%lld\n",tmp); ll sum1=Getsum(W[x]-1,x); ll sum2=Getsize(W[x]-1); ll sum3=Getsum(n,x); tmp-=(sum2-sum1*2+sum3); Del(W[x],x); } return 0;}
阅读全文
2 0
- 数据结构学习——动态逆序对
- 【数据结构】(树套树)BZOJ3295动态逆序对
- CDQ分治——BZOJ3295/Luogu3157 [CQOI2011]动态逆序对
- cdq分治——P3157 [CQOI2011]动态逆序对
- 动态逆序对[CDQ]
- CQOI2011-动态逆序对
- BZOJ3295动态逆序对
- 【cqoi2011】动态逆序对
- HYSBZ3295-动态逆序对
- bzoj3295 动态逆序对
- 动态逆序对
- 数据结构—(3)逆序输出
- LINTCODE——逆序对
- BZOJ 3295 动态逆序对
- 【CQOI2011】【BZOJ3295】动态逆序对
- 3295: [Cqoi2011]动态逆序对
- BZOJ3295 CQOI2011 动态逆序对
- [BZOJ3295] [Cqoi2011]动态逆序对
- 中国大陆省市区县三级、四级菜单数据整理
- 哪些网站使用了vue,及其seo
- 刘强东万字长文谈战略:京东要从“一体化”走向“一体化的开放”
- BZOJ 3675 [Apio2014]序列分割 动态规划+斜率优化
- 解决问题:win10下VS2013报错:此电脑没有安装ActiveX控件
- 数据结构学习——动态逆序对
- JavaScript在JSP页面加载与执行顺序
- Spring Cache扩展:注解失效时间+主动刷新缓存
- 20171020testData
- 在textView中添加图片并设置图片大小
- exports和module.exports的区别
- ubuntu16.04设置ssh免密码登录
- bug整理1(未完成)
- C++中set用法详解