【线段树】HDU1394 - Minimum Inversion Number
2024-10-19 17:23:21
【题目大意】
给出0..n-1组成的一段数,可以移动前几个数到结尾。求出最小的逆序对个数。
【思路】
先用线段树求出逆序对,方法和树状数组是一样的。然后对于当前第一个数num[0],在它之后比它小的数有num[0],则它移动到末位之后减小的逆序对是num[0],增加的是n-1-num[0]。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define lson l,m,root<<1
#define rson m+1,r,root<<1|1
const int MAXN=+;
int n,num[MAXN];
int sum[MAXN*];
int inver[MAXN]; void pushUP(int root)
{
sum[root]=sum[root<<]+sum[root<<|];
} void build(int l,int r,int root)
{
if (l==r)
{
sum[root]=;
return;
}
int m=(l+r)>>;
build(lson);
build(rson);
pushUP(root);
} void update(int p,int delta,int l,int r,int root)
{
if (l==r)
{
sum[root]+=delta;
return;
}
int m=(l+r)>>;
if (p<=m) update(p,delta,lson);
if (p>m) update(p,delta,rson);
pushUP(root);
} int query(int L,int R,int l,int r,int root)
{
if (L<=l && r<=R)
{
return sum[root];
}
int m=(l+r)>>,res=;
if (L<=m) res+=query(L,R,lson);
if (R>m) res+=query(L,R,rson);
return res; } int main()
{
while (scanf("%d",&n)!=EOF)
{
build(,n-,);
for (int i=;i<n;i++)
{
scanf("%d",&num[i]);
inver[i]=query(num[i]+,n,,n,);
update(num[i]+,,,n,);
}
int tempsum=;
for (int i=;i<n;i++) tempsum+=inver[i];
int ans=tempsum;
for (int i=;i<n;i++)
{
tempsum-=num[i];
tempsum+=n--num[i];
ans=min(ans,tempsum);
}
cout<<ans<<endl;
}
return ;
}
最新文章
- the operation was attempted on an empty geometry Arcgis Project异常
- 破解加密PDF文件pdfcrack
- Android jar包的导出和使用
- The main difference between Java &; C++(转载)
- freebsd 显示中文
- [转]通过PowerShell工具跨多台服务器执行SQL脚本
- angularjs 相关资料
- 什么是Ajax无刷新技术?
- Java获取最后插入MySQL记录的自增ID值方法
- POJ 3422 Kaka&#39;s Matrix Travels(最小费用最大流)
- oracle中exp,imp的使用详解
- python网上开发执行环境
- PAT (Advanced Level) 1020. Tree Traversals (25)
- PC-lint集成于SourceInsight 范例以及简单分析;提高代码的健壮性;
- 数据标记系列——图像分割 &; PolygonRNN++(一)
- kubernetes1.4新特性(一):支持sysctl命令
- Cotex-M4简介
- Linux系统下tomcat的配置
- OOP ⑴
- js中toFixed() 的使用(转)