题意:
给出n个数..问循环排序后的最小逆序数
思路:
根据出现次序..用线段树的sum记录某一区间出现次数..
把出现的数值a[i] 更新到 sum[a[i]]..
根据题意..当每一次更新的之前..都对当前位置到最后位置出现的数进行查询..
即可得到出现比该值早而又比该值大的数的个数..即满足逆序数对的定义..
所以求和就可得到逆序数对的值..
当每一次把队头的值移到队尾..
逆序数对就减少了当前值(a[i]-1)<逆序数对包含该值的都没有了..>..
但是还有一些逆序数对增加了..(加入到队尾时可与该数组成逆序数对的..)即n-a[i]对..
所以每一次循环后存在的逆序数对个数就是:sum = sum-(a[i]-1) + (n-a[i]);
Tips:
暴力超时了..所以用线段树来算..
Code:
View Code
1 #include <stdio.h> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int MAXN = 5010; 7 int sum[MAXN<<2]; 8 int a[MAXN]; 9 10 void pushup(int rt) 11 { 12 sum[rt] = sum[rt<<1] + sum[rt<<1|1]; 13 } 14 15 void creat(int l, int r, int rt) 16 { 17 sum[rt] = 0; 18 if(l == r) 19 return; 20 int mid = (l+r)>>1; 21 creat(l, mid, rt<<1); 22 creat(mid+1, r, rt<<1|1); 23 pushup(rt); 24 } 25 26 void modify(int p,int l, int r, int rt) 27 { 28 if(l == r) { 29 sum[rt]++; 30 return; 31 } 32 int mid = (l+r)>>1; 33 if(p <= mid) modify(p, l, mid, rt<<1); 34 else modify(p, mid+1, r, rt<<1|1); 35 pushup(rt); 36 } 37 38 int query(int l, int r, int L, int R, int rt) 39 { 40 if(l <= L && R <= r) { 41 return sum[rt]; 42 } 43 int mid = (L+R)>>1; 44 int res = 0; 45 if(l <= mid) res += query(l, r, L, mid, rt<<1); 46 if(r > mid) res += query(l, r, mid+1, R, rt<<1|1); 47 return res; 48 } 49 50 int main() 51 { 52 int i, j, k; 53 int n, sum; 54 while(scanf("%d", &n) != EOF) 55 { 56 int s = 0; 57 creat(1, n, 1); 58 59 for(i = 0; i < n; ++i) { 60 scanf("%d", &a[i]); 61 a[i]++; 62 s += query(a[i], n, 1, n, 1); 63 modify(a[i], 1, n, 1); 64 } 65 66 int mi = 0x1f1f1f1f;///!!! 67 for(i = 0; i < n; ++i) { 68 s = s-(a[i] - 1)+(n-a[i]); 69 mi = min(mi, s); 70 } 71 72 printf("%d\n", mi); 73 } 74 return 0; 75 } 76 77 /* 78 int main() 79 { 80 int i, j, k; 81 int n; 82 while(scanf("%d", &n) != EOF) 83 { 84 for(i = 0; i < n; ++i) { 85 scanf("%d", &a[i]); 86 } 87 88 int mi = 0x1f1f1f1f, s = 0; 89 for(i = 0; i < n; ++i) { 90 creat(1, n, 1); 91 s = 0; 92 for(j = 0; j < n; ++j) { 93 s += query(a[(i+j)%n]+1, n, 1, n, 1); 94 modify(a[(j+i)%n]+1, 1, n, 1); 95 } 96 mi = min(mi, s); 97 } 98 99 printf("%d\n", mi); 100 } 101 return 0; 102 } 103 */