hdu - 1394 Minimum Inversion Number(线段树水题)

时间:2023-02-05 03:15:37

http://acm.hdu.edu.cn/showproblem.php?pid=1394

很基础的线段树.

先查询在更新,如果后面的数比前面的数小肯定会查询到前面已经更新过的值,这时候返回的sum就是当前数的逆序数.

这样查询完之后得到初始数列的逆序数,要求得所有序列的最小逆序数,还需要循环一次.

设初始序列abcde中逆序数为k,小于a的个数是t-1那么大于a的个数就是n-t,当把a左移一位,原来比a大的都变成了a的逆序对,即逆序数增加了n-t,但是原来比a小的数都变成了顺序,

因此逆序数减少了t-1,所以新的序列的逆序数为k+=n-t-t+1;

 #include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>
#include <deque>
//#pragma comment(linker, "/STACK:102400000,102400000")
#define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll long long
#define INF 0x7f7f7f7f
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0) #define L(x) (x) << 1
#define R(x) (x) << 1 | 1
#define MID(l, r) (l + r) >> 1
#define Min(x, y) (x) < (y) ? (x) : (y)
#define Max(x, y) (x) < (y) ? (y) : (x)
#define E(x) (1 << (x))
#define iabs(x) (x) < 0 ? -(x) : (x)
#define OUT(x) printf("%I64d\n", x)
#define lowbit(x) (x)&(-x)
#define Read() freopen("a.txt", "r", stdin)
#define Write() freopen("b.txt", "w", stdout);
#define maxn 5010
#define maxv 50010
#define mod 1000000000
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 int sum[maxn<<]; void PushUP(int rt)
{
sum[rt]=sum[rt<<]+sum[rt<<|];
} void build(int l,int r,int rt)
{
sum[rt]=;
if(l==r) return;
int m=(l+r)>>;
build(lson);
build(rson);
} void update(int p,int l,int r,int rt)
{
if(l==r)
{
sum[rt]++;
return;
}
int m=(l+r)>>;
if(p<=m) update(p,lson);
else update(p,rson);
PushUP(rt);
} int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return sum[rt];
}
int m=(l+r)>>;
int ret=;
if(L<=m) ret+=query(L,R,lson);
if(R>m) ret+=query(L,R,rson);
return ret;
} int x[maxn];
int main()
{
//Read();
int n;
while(~scanf("%d",&n))
{
build(,n-,);
int ans=;
for(int i=;i<n;i++)
{
scanf("%d",&x[i]);
ans+=query(x[i],n-,,n-,);
update(x[i],,n-,);
}
int ret=ans;
for(int i=;i<n;i++)
{
ans+=n-x[i]-x[i]-;
ret=min(ret,ans);
}
printf("%d\n",ret);
}
return ;
}