标签:杠铃 树状 int 51nod3121 数组 小陶 define
3121 小陶与杠铃片
小陶在举重队负责后勤工作。举重队的训练场中有一个区域一排码放了n片杠铃片,每天运动员们训练完之后会将杠铃片放回,之后小陶需要重新整理杠铃片的顺序,使它们由轻到重依次排好。由于杠铃片很重,小陶每次只能选两片相邻的杠铃片,交换它们的位置。现在小陶想知道,这一天他至少需要交换多少次才能整理完毕?
已知n<=200000,0<=杠铃片重量<=200000。
输入
第一行一个正整数n,表示有n片杠铃片;
第二行n个整数,表示运动员们放回后每片杠铃片依次的重量。
输出
输出一个整数,表示小陶至少交换的次数。
数据范围
对于30%的数据: n<=5000
对于60%的数据: n<=30000
对于100%的数据: n<=200000,0<=杠铃片重量<=200000
输入样例
10
16808 75250 50074 143659 108931 11273 27545 50879 177924 37710
输出样例
20
解析:
树状数组求逆序对
对于序列中的每个数,如果我们能设法快速找出有多少个,满足i<j且就好了
其实也可以先找满足i<j且的个数cnt,那么j-cnt就是我们上面要求的数量
怎么找呢?
我们可以用树状数组去维护这样一个数组: num[i]表示权值为i的数的个数。
那么我们依次枚举每个数并将其加入树状数组,在需要统计满足i<j且的个数时,我们使得树状数组里加入了,然后在树状数组中统计即可,这是一段区间和,而且是一段前缀和,非常容易求出。
放代码:
#include<bits/stdc++.h>
using namespace std;
#define lowbit(i) (i & -i)
#define MX 200000
#define N 200020
int n;
int a[N], C[N];
void add(int x, int c) {
for (int i = x; i <= MX; i += lowbit(i))
C[i] += c;
}
int ask(int x) {
int ret = 0;
for (int i = x; i; i -= lowbit(i))
ret += C[i];
return ret;
}
long long ans;
int main() {
ios::sync_with_stdio(false);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++) {
ans += (i - 1) - ask(a[i]);
add(a[i], 1);
}
cout << ans << endl;
}
标签:杠铃,树状,int,51nod3121,数组,小陶,define 来源: https://blog.csdn.net/ZCH1901/article/details/121109420
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。