欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

1/31P1908逆序对P1774

时间:2023-06-05

https://www.luogu.com.cn/problem/P1908
https://www.luogu.com.cn/problem/P1774
同样的代码可交两题
虽然不太想写博客,但这题比较巧妙,单独拿出来总结一下。一共三个知识点:
1.树状数组的基本应用。
2.离散化的处理:在不改变数据大小的情况下,对数据进行相应的处理,防止RE。一句话就是哦那个过下标记录数据大小的相对位置。
(树状数组的应用和离散化都是降低复杂度的有力工具)
3.最关键的是,数据是有可能出现数值相同的情况,要进行特殊处理,不能以快排结束,破坏了相对位置。
最难理解的是这两条语句:

for(register ll i=1;i<=n;i++) { add(b[i],1); ans+=i-sum(b[i]); }

b[i]记录的是原数据从小到大排序后的下标情况,数值是从小到大加入,但加入的位置是原数据的位置。
sum(b[i])表示1到b[i]总共有多少个数,然后读入循环走几轮就理解离散化原理了,太妙了,我现在只知道怎么做,但具体提为什么还不清楚。

#include using namespace std;typedef long long ll;const int maxn=5e5+5; //数据要用到离散化struct node{ ll val,order;}e[maxn];bool cmp(node e1,node e2){ return e1.val0) { ret+=d[x];x-=x&-x; } return ret;}int main(){ ll ans=0; scanf("%lld",&n); for(register ll i=1;i<=n;i++) { scanf("%lld",&e[i].val); e[i].order=i; } sort(e+1,e+n+1,cmp); b[e[1].order]=1; for(register ll i=2,ct=1;i<=n;i++) { if(e[i].val==e[i-1].val) b[e[i].order]=ct; else b[e[i].order]=++ct; } for(register ll i=1;i<=n;i++) { add(b[i],1); ans+=i-sum(b[i]); } printf("%lld",ans); return 0;}

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。