1 条题解
-
0
自动搬运
来自洛谷,原作者为

ghostdoglzd
rp++搬运于
2025-08-24 22:19:15,当前版本为作者最后更新于2020-10-15 20:01:27,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
原题
题意概括:
- 有长为的序列 ,。
- 请你按 依次输出把大于 的 变为 后逆序对的个数。
思路:
这是一道很好的思考题,我们可以把 按从小到大的顺序排序,对于每个 ,在原序列中它前面比它大的数的个数即为其对 时的答案的贡献。然后从 到 枚举 。每次枚举先输出答案,再把答案加上等于 的 的贡献即可。
这个贡献可以利用树状数组维护区间和把复杂度降为 。具体实现方式为先往树状数组的每一位上放。然后每遍历到一个 ,将它在原序列中的位置对应的树状数组值改为 ,其贡献即为它在原序列中的位置前还有多少 ,即 ,( 为 在原序列中的位置)。
#include<iostream> #include<cstdio> #include<algorithm> #define int long long using namespace std; inline int rread(){ int x=0; char c=getchar(),o=' '; while(c<'0'||c>'9')o=c,c=getchar(); while(c>='0'&&c<='9')x*=10,x+=(c^48),c=getchar(); if(o=='-')x=-x; return x; } inline int lowbit(int x){ return x&(-x); } struct node{ int a,num; }nd[100010]; bool operator <(const node& x,const node& y){ return (x.a==y.a)?x.num<y.num:x.a<y.a; } int n,tree[100010]; inline void change(int x,int c){ while(x<=n){ tree[x]+=c; x+=lowbit(x); } } inline int query(int x){ int ans=0; while(x>0){ ans+=tree[x]; x-=lowbit(x); } return ans; } signed main(){ n=rread(); for(int i=1;i<=n;i++){ nd[i].a=rread(); nd[i].num=i; change(nd[i].num,1); } sort(nd+1,nd+1+n); int ans=0; int in=1; for(int i=0;i<n;i++){ cout<<ans<<'\n'; int t=in; while(i==nd[t].a){ ans+=query(nd[t].num-1); change(nd[t].num,-1); t++; } in=t; } return 0; }
更新日志
2020.10.16 修改了链接
- 1
信息
- ID
- 5329
- 时间
- 2000ms
- 内存
- 250MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者