您的位置:首页 > 其它

HDU 1394 Minimum Inversion Number(线段树)

2017-09-06 00:29 316 查看
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <list>
#define INF 0x3f3f3f
#define maxn 105000
#define juzheng 300

#define ll long long

using namespace std;

//Date:2017-9-5
//Author:HarryBlackCat

struct xx{
int left;
int right;
int val;
}tree[maxn];

int n,m,arr[maxn],sum;

void bulid_tree(int node,int left,int right){//建立线段树,让值初始化为0
tree[node].left = left;
tree[node].right = right;
tree[node].val = 0;

if(left == right)
return;
else{
int mid = (left + right) / 2;
bulid_tree(node * 2,left,mid);
bulid_tree(node * 2 + 1,mid + 1,right);
}
}

void add(int node,int index,int val){//按序列更新值
if(tree[node].left == index && tree[node].right == index)
tree[node].val = val;
else{
int mid = (tree[node].left + tree[node].right) / 2;
if(index > mid)
add(node * 2 + 1,index,val);
else
add(node * 2,index,val);

tree[node].val = tree[node * 2].val + tree[node * 2 + 1].val;
}
}

void get_sum(int node,int left,int right){//计算left-right之间标记的值加起来即为逆序数
if(tree[node].left >= left && tree[node].right <= right)
sum += tree[node].val;
else{
int mid = (tree[node].left + tree[node].right) / 2;
if(left > mid)
get_sum(node * 2 + 1,left,right);
else if(right <= mid)
get_sum(node * 2,left,right);
else{
get_sum(node * 2,left,right);
get_sum(node * 2 + 1,left,right);
}
}
}

int main(){
while(~scanf("%d",&n)){
for(int i = 1;i <= n;i++)
scanf("%d",&arr[i]);

bulid_tree(1,0,n - 1);

int ans = 0;
for(int i = 1;i <= n;i++){
sum = 0;
get_sum(1,arr[i],n - 1);
ans += sum;//计算序列一开始的逆序数
add(1,arr[i],1);//记录
}

int min2 = INF;
for(int i = 1;i <= n;i++){
ans = ans - arr[i] + n - 1 - arr[i];//因为序列是按照0-(n - 1)排列的,可以按照规律推出此公式
min2 = min(min2,ans);//找到最小的逆序数
}

printf("%d\n",min2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: