洛谷——P1966 火柴排队&&P1774 最接近神的人_NOI导刊2010提高(02)
P1966 火柴排队
这题贪心显然,即将两序列中第k大的数的位置保持一致,证明略;
树状数组求逆序对啦
浅谈树状数组求逆序对及离散化的几种方式及应用
方法:从前向后每次将数插入到bit(树状数组)中,求其前缀和(在它之前插入且比它小的数),那么用i(当前插入的数的总数)- 前缀和就是其(以c[i]为结尾)逆序对对数
这个题需要将一个序列按照另一个序列排序,因为只需要移动一个序列,sort排序就有了第k小的数的下标
c[a[i].id]=b[i].id
第i小的数在a中的位置就是b中第i小的数应放的位置,相当于以第一个数列为关键字排序第二个数列
#include<bits/stdc++.h> #define N 1010100 using namespace std; const int mod=99999997; int n,c[N],bit[N],ans; struct node{ int x,id; }a[N],b[N]; bool cmp(node A,node B){ return A.x<B.x; } int lowbit(int k){ return k&(-k); } void add(int x,int w){ while(x<=n){ bit[x]+=w; bit[x]%=mod; x+=lowbit(x); } } int sum(int x){ int res=0; while(x){ res+=bit[x]; x-=lowbit(x); res%=mod; } return res%mod; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i].x),a[i].id=i; for(int i=1;i<=n;i++) scanf("%d",&b[i].x),b[i].id=i; sort(a+1,a+1+n,cmp); sort(b+1,b+1+n,cmp); for(int i=1;i<=n;i++) c[a[i].id]=b[i].id; for(int i=1;i<=n;i++){ add(c[i],1); ans=(ans+(i-sum(c[i])))%mod; } printf("%d\n",ans); return 0; }
P1774 最接近神的人_NOI导刊2010提高(02)
同样的离散化,只不过是从后向前插入,那么其前缀和就是逆序数。
#include<bits/stdc++.h> #define N 500005 #define ll long long using namespace std; int n,h[N],c[N]; ll ans; struct node{ int y;ll x; bool operator<(const node A)const { return x==A.x ? y<A.y :x<A.x; } }e[N]; void update(int k,int x){ for(;k<=n;k+=k&-k) c[k]+=x; } ll query(int k){ ll an=0; for(;k;k-=k&-k) an+=c[k]; return an; } int main() { cin>>n; for(int i=1;i<=n;i++) scanf("%lld",&e[e[i].y=i].x); sort(e+1,e+1+n); for(int i=n;i;i--){ ans+=query(e[i].y-1); update(e[i].y,1); }cout<<ans; // printf("%lld",ans); return 0; }
博主蒟蒻,若有出错的地方,敬请指出。
如有侵犯您版权的地方,请快速联系我,我会撤回本博文。
· 理解 C# 中的各类指针
· C#多线程编程精要:从用户线程到线程池的效能进化论
· 如何反向绘制出 .NET程序 异步方法调用栈
· 领域驱动设计实战:聚合根设计与领域模型实现
· 突破Excel百万数据导出瓶颈:全链路优化实战指南
· 理解 C# 中的各类指针
· DeepSeek+Coze实战:从0到1搭建小红书图文改写智能体(喂饭级教程)
· 【SQL周周练】一千条数据需要做一天,怎么用 SQL 处理电表数据(如何动态构造自然月)
· C#/.NET/.NET Core技术前沿周刊 | 第 37 期(2025年5.1-5.11)
· 如何医治一条慢SQL?