HDU 1394 Minimum Inversion Number(线段树)

来源:互联网 发布:360vr全景通源码 编辑:程序博客网 时间:2024/05/22 13:37
#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 longusing namespace std;//Date:2017-9-5//Author:HarryBlackCatstruct 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);elseadd(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;}