线段树
假如考虑iValue[i],则要先将iValue[1]->iValue[i-1]放在线段树里面,计算每一段里面包含多少个已遍历值(iValue[1]->iValue[i-1]),然后查找iValue[i]+1->n的值有多少个,这样的话,就相当与在查找iValue[1]->iValue[i-1]有多少个值是在iValue[i]+1->n范围的。(这一题目也可以用树状数组做)
代码如下:
1 #include <iostream> 2 3 using namespace std; 4 5 struct node 6 { 7 int low,high; 8 int value; 9 }seg[10005]; 10 int iValue[5005]; 11 int ans_one; 12 13 void build_tree(int root,int low,int high) 14 { 15 seg[root].low = low; 16 seg[root].high = high; 17 seg[root].value = 0; 18 if(low == high) 19 { 20 return; 21 } 22 23 int mid = (low + high) >> 1; 24 build_tree(root*2,low,mid); 25 build_tree(root*2+1,mid+1,high); 26 } 27 28 void s_tree(int root,int low,int high) 29 { 30 if(low <= seg[root].low && high >= seg[root].high) 31 { 32 ans_one +=seg[root].value; 33 return; 34 } 35 36 int mid = (seg[root].low + seg[root].high) >> 1; 37 if(high <= mid) 38 { 39 s_tree(root*2,low,high); 40 }else if(low > mid) 41 { 42 s_tree(root*2+1,low,high); 43 }else 44 { 45 s_tree(root*2,low,mid); 46 s_tree(root*2+1,mid+1,high); 47 } 48 } 49 50 void s_update(int root,int sValue) 51 { 52 seg[root].value ++; 53 if(seg[root].low == seg[root].high) 54 { 55 return; 56 } 57 int mid = (seg[root].low + seg[root].high) >> 1; 58 if(mid >= sValue) 59 { 60 s_update(root*2,sValue); 61 }else 62 { 63 s_update(root*2+1,sValue); 64 } 65 } 66 int main() 67 { 68 int n; 69 while(cin >> n) 70 { 71 for(int i = 1;i <= n;i ++) 72 { 73 cin >> iValue[i]; 74 iValue[i] ++; 75 } 76 77 build_tree(1,1,n); 78 ans_one = 0; 79 for(int i = 1;i <= n;i ++) 80 { 81 if(iValue[i] <= n-1) s_tree(1,iValue[i]+1,n); 82 s_update(1,iValue[i]); 83 } 84 85 int ans = -1; 86 for(int i = 2;i <= n;i ++) 87 { 88 ans_one += (n-iValue[i-1]) - (iValue[i-1] - 1); 89 if(ans == -1 || ans > ans_one) 90 { 91 ans = ans_one; 92 } 93 } 94 cout << ans << endl; 95 } 96 return 0; 97 }